packagekit: Add 2 patched for packagekit.
authorJulian_chu <julian_chu@openmoko.com>
Mon, 2 Jun 2008 03:19:56 +0000 (11:19 +0800)
committerHolger Hans Peter Freyther <zecke@selfish.org>
Tue, 28 Oct 2008 21:48:50 +0000 (22:48 +0100)
             New stuff will be:
              * Added a new error enum to packagekit to support "corrupt-package" message.
              * Improve the error handling for update and install functions, with new opkg.

packages/packagekit/files/01_d1e096c3267c1c9492041382b954e9327bc8bbec.patch [new file with mode: 0644]
packages/packagekit/files/02_9ced8313fb12f0f89ad6ced7c0fdc7241ff00d77.patch [new file with mode: 0644]
packages/packagekit/files/d1e096c3267c1c9492041382b954e9327bc8bbec.patch [deleted file]
packages/packagekit/packagekit_git.bb

diff --git a/packages/packagekit/files/01_d1e096c3267c1c9492041382b954e9327bc8bbec.patch b/packages/packagekit/files/01_d1e096c3267c1c9492041382b954e9327bc8bbec.patch
new file mode 100644 (file)
index 0000000..f050a50
--- /dev/null
@@ -0,0 +1,2938 @@
+diff --git a/backends/alpm/pk-backend-alpm.c b/backends/alpm/pk-backend-alpm.c
+index 3270e42..45e7a44 100644
+--- a/backends/alpm/pk-backend-alpm.c
++++ b/backends/alpm/pk-backend-alpm.c
+@@ -895,7 +895,7 @@ backend_get_repo_list (PkBackend *backend, PkFilterEnum filters)
+ static gboolean
+ backend_install_files_thread (PkBackend *backend)
+ {
+-      pk_backend_no_percentage_updates (backend);
++      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+       gchar **full_paths = pk_backend_get_strv (backend, "full_paths");
+@@ -1050,7 +1050,7 @@ backend_install_packages (PkBackend *backend, gchar **package_ids)
+ static gboolean
+ backend_refresh_cache_thread (PkBackend *backend)
+ {
+-      pk_backend_no_percentage_updates (backend);
++      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+       if (alpm_trans_init (PM_TRANS_TYPE_SYNC, PM_TRANS_FLAG_NOSCRIPTLET, cb_trans_evt, cb_trans_conv, cb_trans_progress) != 0) {
+               pk_backend_error_code (backend, PK_ERROR_ENUM_TRANSACTION_ERROR, alpm_strerror (pm_errno));
+diff --git a/backends/apt/pk-apt-build-db.cpp b/backends/apt/pk-apt-build-db.cpp
+index d47c348..885275d 100644
+--- a/backends/apt/pk-apt-build-db.cpp
++++ b/backends/apt/pk-apt-build-db.cpp
+@@ -40,7 +40,7 @@ void apt_build_db(PkBackend * backend, sqlite3 *db)
+       sqlite3_stmt *package = NULL;
+       pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY);
+-      pk_backend_no_percentage_updates(backend);
++      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+       sdir = g_build_filename(_config->Find("Dir").c_str(),_config->Find("Dir::State").c_str(),_config->Find("Dir::State::lists").c_str(), NULL);
+       dir = g_dir_open(sdir,0,&error);
+diff --git a/backends/apt/pk-sqlite-pkg-cache.cpp b/backends/apt/pk-sqlite-pkg-cache.cpp
+index 770fcdf..1bf9a50 100644
+--- a/backends/apt/pk-sqlite-pkg-cache.cpp
++++ b/backends/apt/pk-sqlite-pkg-cache.cpp
+@@ -81,7 +81,7 @@ sqlite_search_packages_thread (PkBackend *backend)
+       const gchar *search;
+       pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY);
+-      pk_backend_no_percentage_updates(backend);
++      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+       type = pk_backend_get_uint (backend, "type");
+       search = pk_backend_get_string (backend, "search");
+@@ -176,7 +176,7 @@ sqlite_get_details_thread (PkBackend *backend)
+       }
+       pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY);
+-      pk_backend_no_percentage_updates(backend);
++      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+       pk_debug("finding %s", pi->name);
+diff --git a/backends/box/pk-backend-box.c b/backends/box/pk-backend-box.c
+index b7b8167..9263781 100644
+--- a/backends/box/pk-backend-box.c
++++ b/backends/box/pk-backend-box.c
+@@ -138,7 +138,7 @@ backend_find_packages_thread (PkBackend *backend)
+               filter_box = filter_box | PKG_SEARCH_DETAILS;
+       }
+-      pk_backend_no_percentage_updates (backend);
++      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+       db = db_open();
+diff --git a/backends/dummy/pk-backend-dummy.c b/backends/dummy/pk-backend-dummy.c
+index 49d4e5a..2df445e 100644
+--- a/backends/dummy/pk-backend-dummy.c
++++ b/backends/dummy/pk-backend-dummy.c
+@@ -254,7 +254,7 @@ static void
+ backend_get_updates (PkBackend *backend, PkFilterEnum filters)
+ {
+       pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
+-      pk_backend_no_percentage_updates (backend);
++      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+       /* check network state */
+       if (!pk_backend_is_online (backend)) {
+               pk_backend_error_code (backend, PK_ERROR_ENUM_NO_NETWORK, "Cannot check when offline");
+@@ -268,6 +268,8 @@ static gboolean
+ backend_install_timeout (gpointer data)
+ {
+       PkBackend *backend = (PkBackend *) data;
++      guint sub_percent;
++
+       if (_progress_percentage == 100) {
+               pk_backend_finished (backend);
+               return FALSE;
+@@ -283,9 +285,18 @@ backend_install_timeout (gpointer data)
+               pk_backend_package (backend, PK_INFO_ENUM_INSTALLING,
+                                   "gtkhtml2-devel;2.19.1-0.fc8;i386;fedora",
+                                   "Devel files for gtkhtml");
++              /* this duplicate package should be ignored */
++              pk_backend_package (backend, PK_INFO_ENUM_INSTALLING,
++                                  "gtkhtml2-devel;2.19.1-0.fc8;i386;fedora", NULL);
+               pk_backend_set_status (backend, PK_STATUS_ENUM_INSTALL);
+       }
+-      _progress_percentage += 10;
++      if (_progress_percentage > 30 && _progress_percentage < 50) {
++              sub_percent = ((gfloat) (_progress_percentage - 30.0f) / 20.0f) * 100.0f;
++              pk_backend_set_sub_percentage (backend, sub_percent);
++      } else {
++              pk_backend_set_sub_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
++      }
++      _progress_percentage += 1;
+       pk_backend_set_percentage (backend, _progress_percentage);
+       return TRUE;
+ }
+@@ -348,7 +359,7 @@ backend_install_packages (PkBackend *backend, gchar **package_ids)
+       pk_backend_package (backend, PK_INFO_ENUM_DOWNLOADING,
+                           "gtkhtml2;2.19.1-4.fc8;i386;fedora",
+                           "An HTML widget for GTK+ 2.0");
+-      _signal_timeout = g_timeout_add (1000, backend_install_timeout, backend);
++      _signal_timeout = g_timeout_add (100, backend_install_timeout, backend);
+ }
+ /**
+@@ -526,7 +537,7 @@ backend_search_name_timeout (gpointer data)
+ static void
+ backend_search_name (PkBackend *backend, PkFilterEnum filters, const gchar *search)
+ {
+-      pk_backend_no_percentage_updates (backend);
++      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+       pk_backend_set_allow_cancel (backend, TRUE);
+       pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
+       _signal_timeout = g_timeout_add (2000, backend_search_name_timeout, backend);
+diff --git a/backends/opkg/pk-backend-opkg.c b/backends/opkg/pk-backend-opkg.c
+index ecc97be..7649bab 100644
+--- a/backends/opkg/pk-backend-opkg.c
++++ b/backends/opkg/pk-backend-opkg.c
+@@ -155,6 +155,38 @@ pk_opkg_progress_cb (opkg_t *opkg, const opkg_progress_data_t *pdata, void *data
+               return;
+       pk_backend_set_percentage (backend, pdata->percentage);
++      if (pdata->package)
++      {
++              gchar *uid;
++              opkg_package_t *pkg = pdata->package;
++              gint status = PK_INFO_ENUM_UNKNOWN;
++
++              uid = g_strdup_printf ("%s;%s;%s;",
++                      pkg->name, pkg->version, pkg->architecture);
++
++              if (pdata->action == OPKG_DOWNLOAD)
++                      status = PK_INFO_ENUM_DOWNLOADING;
++              else if (pdata->action == OPKG_INSTALL)
++                      status = PK_INFO_ENUM_INSTALLING;
++              else if (pdata->action == OPKG_REMOVE)
++                      status = PK_INFO_ENUM_REMOVING;
++
++              pk_backend_package (backend, status, uid, pkg->description);
++              g_free (uid);
++      }
++
++      switch (pdata->action)
++      {
++      case OPKG_DOWNLOAD:
++              pk_backend_set_status (backend, PK_STATUS_ENUM_DOWNLOAD);
++              break;
++      case OPKG_INSTALL:
++              pk_backend_set_status (backend, PK_STATUS_ENUM_INSTALL);
++              break;
++      case OPKG_REMOVE:
++              pk_backend_set_status (backend, PK_STATUS_ENUM_REMOVE);
++              break;
++      }
+ }
+ static gboolean
+@@ -163,8 +195,12 @@ backend_refresh_cache_thread (PkBackend *backend)
+       int ret;
+       ret = opkg_update_package_lists (opkg, pk_opkg_progress_cb, backend);
++
+       if (ret) {
+-              opkg_unknown_error (backend, ret, "Refreshing cache");
++              if (ret == OPKG_DOWNLOAD_FAILED)
++                      pk_backend_error_code (backend, PK_ERROR_ENUM_REPO_NOT_AVAILABLE, NULL);
++              else
++                      opkg_unknown_error (backend, ret, "Refreshing cache");
+       }
+       pk_backend_finished (backend);
+@@ -178,7 +214,7 @@ static void
+ backend_refresh_cache (PkBackend *backend, gboolean force)
+ {
+       pk_backend_set_status (backend, PK_STATUS_ENUM_REFRESH_CACHE);
+-      pk_backend_no_percentage_updates (backend);
++      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+       pk_backend_thread_create (backend, backend_refresh_cache_thread);
+@@ -279,7 +315,7 @@ backend_search_name (PkBackend *backend, PkFilterEnum filters, const gchar *sear
+       pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
+-      pk_backend_no_percentage_updates (backend);
++      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+       params = g_new0 (SearchParams, 1);
+       params->filters = filters;
+@@ -301,7 +337,7 @@ backend_search_description (PkBackend *backend, PkFilterEnum filters, const gcha
+       pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
+-      pk_backend_no_percentage_updates (backend);
++      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+       params = g_new0 (SearchParams, 1);
+       params->filters = filters;
+@@ -320,7 +356,7 @@ backend_search_group (PkBackend *backend, PkFilterEnum filters, const gchar *sea
+       pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
+-      pk_backend_no_percentage_updates (backend);
++      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+       params = g_new0 (SearchParams, 1);
+       params->filters = filters;
+@@ -337,30 +373,52 @@ static gboolean
+ backend_install_packages_thread (PkBackend *backend)
+ {
+       PkPackageId *pi;
+-      gint err;
+-      const gchar *package_id;
++      gint err, i;
++      gchar **package_ids;
+-      package_id = pk_backend_get_string (backend, "pkid");
+-      pk_backend_package (backend, PK_INFO_ENUM_INSTALLING, package_id, NULL);
++      package_ids = pk_backend_get_strv (backend, "pkids");
+-      pi = pk_package_id_new_from_string (package_id);
++      err = 0;
++
++      for (i = 0; package_ids[i]; i++)
++      {
++              pk_backend_package (backend, PK_INFO_ENUM_INSTALLING, package_ids[0], NULL);
+-      err = opkg_install_package (opkg, pi->name, pk_opkg_progress_cb, backend);
+-      if (err != 0)
+-              opkg_unknown_error (backend, err, "Install");
++              pi = pk_package_id_new_from_string (package_ids[0]);
++
++              err = opkg_install_package (opkg, pi->name, pk_opkg_progress_cb, backend);
++              switch (err)
++              {
++              case OPKG_NO_ERROR:
++                      break;
++              case OPKG_DEPENDANCIES_FAILED:
++                      pk_backend_error_code (backend, PK_ERROR_ENUM_DEP_RESOLUTION_FAILED, NULL);
++                      break;
++              case OPKG_PACKAGE_ALREADY_INSTALLED:
++                      pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_ALREADY_INSTALLED, NULL);
++                      break;
++              case OPKG_PACKAGE_NOT_AVAILABLE:
++                      pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_NOT_FOUND, NULL);
++                      break;
++              default:
++                      opkg_unknown_error (backend, err, "Install");
++              }
++              pk_package_id_free (pi);
++              if (err != 0)
++                      break;
++      }
+-      pk_package_id_free (pi);
+       pk_backend_finished (backend);
+       return (err == 0);
+ }
+ static void
+-backend_install_packages (PkBackend *backend, gchar **package_id)
++backend_install_packages (PkBackend *backend, gchar **package_ids)
+ {
+-      pk_backend_no_percentage_updates (backend);
++      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+       pk_backend_set_status (backend, PK_STATUS_ENUM_INSTALL);
+-      pk_backend_set_string (backend, "pkid", package_id[0]);
++      pk_backend_set_strv (backend, "pkids", package_ids);
+       pk_backend_thread_create (backend, backend_install_packages_thread);
+ }
+@@ -369,7 +427,7 @@ static gboolean
+ backend_remove_packages_thread (PkBackend *backend)
+ {
+       PkPackageId *pi;
+-      gint err;
++      gint err, i;
+       gchar **package_ids;
+       gboolean allow_deps;
+       gboolean autoremove;
+@@ -382,19 +440,34 @@ backend_remove_packages_thread (PkBackend *backend)
+       autoremove = GPOINTER_TO_INT (data[2]);
+       g_free (data);
+-      pi = pk_package_id_new_from_string (package_ids[0]);
+-      pk_backend_package (backend, PK_INFO_ENUM_REMOVING, package_ids[0], NULL);
+-
+       opkg_set_option (opkg, "autoremove", &autoremove);
+       opkg_set_option (opkg, "force_removal_of_dependent_packages", &allow_deps);
+-      err = opkg_remove_package (opkg, pi->name, pk_opkg_progress_cb, backend);
++      err = 0;
+-      /* TODO: improve error reporting */
+-      if (err != 0)
+-              opkg_unknown_error (backend, err, "Remove");
++      for (i = 0; package_ids[i]; i++)
++      {
++              pi = pk_package_id_new_from_string (package_ids[0]);
++              pk_backend_package (backend, PK_INFO_ENUM_REMOVING, package_ids[0], NULL);
++
++              err = opkg_remove_package (opkg, pi->name, pk_opkg_progress_cb, backend);
++
++              switch (err)
++              {
++              case OPKG_NO_ERROR:
++                      break;
++              case OPKG_PACKAGE_NOT_INSTALLED:
++                      pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_NOT_INSTALLED, NULL);
++                      break;
++              default:
++                      opkg_unknown_error (backend, err, "Remove");
++              }
++              pk_package_id_free (pi);
++
++              if (err != 0)
++                      break;
++      }
+-      pk_package_id_free (pi);
+       pk_backend_finished (backend);
+       return (err == 0);
+ }
+@@ -405,7 +478,7 @@ backend_remove_packages (PkBackend *backend, gchar **package_ids, gboolean allow
+       gpointer *params;
+       pk_backend_set_status (backend, PK_STATUS_ENUM_REMOVE);
+-      pk_backend_no_percentage_updates (backend);
++      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+       /* params is a small array we can pack our thread parameters into */
+       params = g_new0 (gpointer, 2);
+@@ -450,7 +523,7 @@ static void
+ backend_update_system (PkBackend *backend)
+ {
+       pk_backend_set_status (backend, PK_STATUS_ENUM_UPDATE);
+-      pk_backend_no_percentage_updates (backend);
++      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+       pk_backend_thread_create (backend, backend_update_system_thread);
+ }
+@@ -478,8 +551,14 @@ backend_update_package_thread (PkBackend *backend)
+       }
+       err = opkg_upgrade_package (opkg, pi->name, pk_opkg_progress_cb, backend);
+-
+-      if (err != 0) {
++      switch (err)
++      {
++      case OPKG_NO_ERROR:
++              break;
++      case OPKG_PACKAGE_NOT_INSTALLED:
++              pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_NOT_INSTALLED, NULL);
++              break;
++      default:
+               opkg_unknown_error (backend, err, "Update package");
+       }
+@@ -494,7 +573,7 @@ backend_update_packages (PkBackend *backend, gchar **package_ids)
+       gint i;
+       pk_backend_set_status (backend, PK_STATUS_ENUM_UPDATE);
+-      pk_backend_no_percentage_updates (backend);
++      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+       for (i = 0; package_ids[i]; i++) {
+               pk_backend_set_string (backend, "pkgid", package_ids[i]);
+@@ -536,7 +615,7 @@ static void
+ backend_get_updates (PkBackend *backend, PkFilterEnum filters)
+ {
+       pk_backend_set_status (backend, PK_STATUS_ENUM_UPDATE);
+-      pk_backend_no_percentage_updates (backend);
++      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+       pk_backend_thread_create (backend, backend_get_updates_thread);
+ }
+@@ -572,19 +651,26 @@ backend_get_details_thread (PkBackend *backend)
+       if (pi == NULL)
+       {
+               pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_ID_INVALID, "invalid package id");
+-              pk_package_id_free (pi);
++              pk_backend_finished (backend);
+               return FALSE;
+       }
+       pkg = opkg_find_package (opkg, pi->name, pi->version, pi->arch, pi->data);
++      pk_package_id_free (pi);
++
++      if (!pkg)
++      {
++              pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_NOT_FOUND, NULL);
++              pk_backend_finished (backend);
++              return FALSE;
++      }
+       newid = g_strdup_printf ("%s;%s;%s;%s", pkg->name, pkg->version, pkg->architecture, pkg->repository);
+       pk_backend_details (backend, newid, NULL, 0, pkg->description, pkg->url, pkg->size);
+       g_free (newid);
+-      pk_package_id_free (pi);
+       pk_backend_finished (backend);
+       return TRUE;
+ }
+@@ -592,7 +678,7 @@ backend_get_details_thread (PkBackend *backend)
+ static void
+ backend_get_details (PkBackend *backend, const gchar *package_id)
+ {
+-      pk_backend_no_percentage_updates (backend);
++      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+       pk_backend_thread_create (backend, backend_get_details_thread);
+ }
+diff --git a/backends/test/pk-backend-test-dbus.c b/backends/test/pk-backend-test-dbus.c
+index 5dfea32..76686dc 100644
+--- a/backends/test/pk-backend-test-dbus.c
++++ b/backends/test/pk-backend-test-dbus.c
+@@ -36,7 +36,7 @@ static void
+ backend_search_name (PkBackend *backend, PkFilterEnum filters, const gchar *search)
+ {
+       pk_backend_set_allow_cancel (backend, TRUE);
+-      pk_backend_no_percentage_updates (backend);
++      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+       pk_backend_dbus_search_name (dbus, filters, search);
+ }
+diff --git a/backends/test/pk-backend-test-spawn.c b/backends/test/pk-backend-test-spawn.c
+index 2958c05..584f44c 100644
+--- a/backends/test/pk-backend-test-spawn.c
++++ b/backends/test/pk-backend-test-spawn.c
+@@ -35,7 +35,7 @@ backend_search_name (PkBackend *backend, PkFilterEnum filters, const gchar *sear
+ {
+       gchar *filters_text;
+       pk_backend_set_allow_cancel (backend, TRUE);
+-      pk_backend_no_percentage_updates (backend);
++      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+       filters_text = pk_filter_enums_to_text (filters);
+       pk_backend_spawn_helper (spawn, "search-name.sh", filters_text, search, NULL);
+       g_free (filters_text);
+diff --git a/backends/test/pk-backend-test-succeed.c b/backends/test/pk-backend-test-succeed.c
+index 17cdc6e..c046c1d 100644
+--- a/backends/test/pk-backend-test-succeed.c
++++ b/backends/test/pk-backend-test-succeed.c
+@@ -236,7 +236,7 @@ backend_search_name_timeout (gpointer data)
+ static void
+ backend_search_name (PkBackend *backend, PkFilterEnum filters, const gchar *search)
+ {
+-      pk_backend_no_percentage_updates (backend);
++      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+       g_timeout_add (200000, backend_search_name_timeout, backend);
+ }
+diff --git a/backends/yum/helpers/yumBackend.py b/backends/yum/helpers/yumBackend.py
+index f76e27c..5b2da8f 100644
+--- a/backends/yum/helpers/yumBackend.py
++++ b/backends/yum/helpers/yumBackend.py
+@@ -801,6 +801,8 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+         old_throttle = self.yumbase.conf.throttle
+         self.yumbase.conf.throttle = "60%" # Set bandwidth throttle to 60%
+                                            # to avoid taking all the system's bandwidth.
++        old_skip_broken = self.yumbase.conf.skip_broken
++        self.yumbase.conf.skip_broken = 1
+         try:
+             txmbr = self.yumbase.update() # Add all updates to Transaction
+@@ -812,6 +814,7 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+             self.error(ERROR_NO_PACKAGES_TO_UPDATE,"Nothing to do")
+         self.yumbase.conf.throttle = old_throttle
++        self.yumbase.conf.skip_broken = old_skip_broken
+     def refresh_cache(self):
+         '''
+@@ -905,7 +908,7 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+         if txmbrs:
+             self._runYumTransaction()
+         else:
+-            self.error(ERROR_PACKAGE_ALREADY_INSTALLED,"This package could not be installed as it is already installed")
++            self.error(ERROR_PACKAGE_ALREADY_INSTALLED,"The package is already installed")
+     def _checkForNewer(self,po):
+         pkgs = self.yumbase.pkgSack.returnNewestByName(name=po.name)
+@@ -1003,7 +1006,7 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+             return False
+         if self._is_inst(po):
+-            self.error(ERROR_PACKAGE_ALREADY_INSTALLED, "%s is already installed" % str(po))
++            self.error(ERROR_PACKAGE_ALREADY_INSTALLED, "The package %s is already installed" % str(po))
+             return False
+         if len(self.yumbase.conf.exclude) > 0:
+diff --git a/backends/yum2/helpers/testyum2.py b/backends/yum2/helpers/testyum2.py
+index cdec507..85b47f9 100755
+--- a/backends/yum2/helpers/testyum2.py
++++ b/backends/yum2/helpers/testyum2.py
+@@ -80,7 +80,7 @@ try:
+         #iface.GetPackages(FILTER_INSTALLED,'no')
+     if cmd == 'get-repolist' or cmd == 'all':
+         print "Testing GetRepoList()"
+-        iface.GetRepoList()
++        iface.GetRepoList("")
+     if cmd == 'get-updatedetail' or cmd == 'all':
+         print "Testing GetUpdateDetail(PKG_ID)"
+         iface.GetUpdateDetail(PKG_ID)
+diff --git a/backends/yum2/helpers/yumDBUSBackend.py b/backends/yum2/helpers/yumDBUSBackend.py
+index 9cfed94..29f5b03 100755
+--- a/backends/yum2/helpers/yumDBUSBackend.py
++++ b/backends/yum2/helpers/yumDBUSBackend.py
+@@ -434,7 +434,7 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+         try:
+             pkgGroupDict = self._buildGroupDict()
+             fltlist = filters.split(';')
+-            found = {}
++            installed_nevra = [] # yum returns packages as available even when installed
+             if not FILTER_NOT_INSTALLED in fltlist:
+                 # Check installed for group
+@@ -450,21 +450,31 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+                             group = groupMap[cg]           # use the pk group name, instead of yum 'category/group'
+                     if group == key:
+                         if self._do_extra_filtering(pkg, fltlist):
+-                            self._show_package(pkg, INFO_INSTALLED)
++                            package_list.append((pkg,INFO_INSTALLED))
++                    installed_nevra.append(self._get_nevra(pkg))                        
++
+             if not FILTER_INSTALLED in fltlist:
+                 # Check available for group
+                 for pkg in self.yumbase.pkgSack:
+                     if self._cancel_check("Search cancelled."):
+                         # _cancel_check() sets the error message, unlocks yum, and calls Finished()
+                         return
+-                    group = GROUP_OTHER
+-                    if pkgGroupDict.has_key(pkg.name):
+-                        cg = pkgGroupDict[pkg.name]
+-                        if groupMap.has_key(cg):
+-                            group = groupMap[cg]
+-                    if group == key:
+-                        if self._do_extra_filtering(pkg, fltlist):
+-                            self._show_package(pkg, INFO_AVAILABLE)
++
++                    nevra = self._get_nevra(pkg)
++                    if nevra not in installed_nevra:
++                        group = GROUP_OTHER
++                        if pkgGroupDict.has_key(pkg.name):
++                            cg = pkgGroupDict[pkg.name]
++                            if groupMap.has_key(cg):
++                                group = groupMap[cg]
++                        if group == key:
++                            if self._do_extra_filtering(pkg, fltlist):
++                                package_list.append((pkg,INFO_AVAILABLE))
++
++        except yum.Errors.GroupsError,e:
++            self._unlock_yum()
++            self.ErrorCode(ERROR_GROUP_NOT_FOUND, str(e))
++            self.Finished(EXIT_FAILED)
+         except yum.Errors.RepoError,e:
+             self.Message(MESSAGE_NOTICE, "The package cache is invalid and is being rebuilt.")
+             self._refresh_yum_cache()
+@@ -473,6 +483,14 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+             return
++        # basename filter if specified
++        if FILTER_BASENAME in fltlist:
++            for (pkg,status) in self._basename_filter(package_list):
++                self._show_package(pkg,status)
++        else:
++            for (pkg,status) in package_list:
++                self._show_package(pkg,status)
++
+         self._unlock_yum()
+         self.Finished(EXIT_SUCCESS)
+@@ -724,6 +742,11 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+             #we might have a rounding error
+             self.PercentageChanged(100)
++        except yum.Errors.RepoError,e:
++            self._unlock_yum()
++            self.ErrorCode(ERROR_REPO_CONFIGURATION_ERROR,str(e))
++            self.Finished(EXIT_FAILED)
++            self.Exit()
+         except yum.Errors.YumBaseError, e:
+             self._unlock_yum()
+             # This should be a better-defined error, but I'm not sure
+@@ -837,6 +860,7 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+         Needed to be implemented in a sub class
+         '''
+         if inst_file.endswith('.src.rpm'):
++            self._unlock_yum()
+             self.ErrorCode(ERROR_CANNOT_INSTALL_SOURCE_PACKAGE,'Backend will not install a src rpm file')
+             self.Finished(EXIT_FAILED)
+             return
+@@ -1385,30 +1409,30 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+             res = self.yumbase.searchGenerator(searchlist, [key])
+             fltlist = filters.split(';')
+-            available = []
+-            count = 1
++            seen_nevra = [] # yum returns packages as available even when installed
++            pkg_list = [] # only do the second iteration on not installed pkgs
++            package_list = [] #we can't do emitting as found if we are post-processing
++
+             for (pkg,values) in res:
+                 if self._cancel_check("Search cancelled."):
+                     return False
+                 # are we installed?
+                 if pkg.repo.id == 'installed':
+-                    if FILTER_NOT_INSTALLED not in fltlist:
+-                        if self._do_extra_filtering(pkg,fltlist):
+-                            count+=1
+-                            if count > 100:
+-                                break
+-                            self._show_package(pkg, INFO_INSTALLED)
++                    if self._do_extra_filtering(pkg,fltlist):
++                        package_list.append((pkg,INFO_INSTALLED))
++                        seen_nevra.append(self._get_nevra(pkg))
+                 else:
+-                    available.append(pkg)
++                    pkg_list.append(pkg)
+-            # Now show available packages.
+-            if FILTER_INSTALLED not in fltlist:
+-                for pkg in available:
+-                    if self._cancel_check("Search cancelled."):
+-                        return False
+-                    if self._do_extra_filtering(pkg,fltlist):
+-                        self._show_package(pkg, INFO_AVAILABLE)
++            for pkg in pkg_list:
++                if self._cancel_check("Search cancelled."):
++                    return False
++                nevra = self._get_nevra(pkg)
++                if nevra not in seen_nevra:
++                    if self._do_extra_filtering(pkg,fltlist):
++                        package_list.append((pkg,INFO_AVAILABLE))
++                        seen_nevra.append(self._get_nevra(pkg))
+         except yum.Errors.RepoError,e:
+             self.Message(MESSAGE_NOTICE, "The package cache is invalid and is being rebuilt.")
+             self._refresh_yum_cache()
+@@ -1417,13 +1441,22 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+             return False
++        # basename filter if specified
++        if FILTER_BASENAME in fltlist:
++            for (pkg,status) in self._basename_filter(package_list):
++                self._show_package(pkg,status)
++        else:
++            for (pkg,status) in package_list:
++                self._show_package(pkg,status)
++
+         return True
+     def _do_extra_filtering(self,pkg,filterList):
+         ''' do extra filtering (gui,devel etc) '''
+         for filter in filterList:
+             if filter in (FILTER_INSTALLED, FILTER_NOT_INSTALLED):
+-                continue
++                if not self._do_installed_filtering(filter,pkg):
++                    return False
+             elif filter in (FILTER_GUI, FILTER_NOT_GUI):
+                 if not self._do_gui_filtering(filter, pkg):
+                     return False
+@@ -1433,11 +1466,17 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+             elif filter in (FILTER_FREE, FILTER_NOT_FREE):
+                 if not self._do_free_filtering(filter, pkg):
+                     return False
+-            elif filter in (FILTER_BASENAME, FILTER_NOT_BASENAME):
+-                if not self._do_basename_filtering(filter, pkg):
+-                    return False
+         return True
++    def _do_installed_filtering(self,flt,pkg):
++        isInstalled = False
++        if flt == FILTER_INSTALLED:
++            wantInstalled = True
++        else:
++            wantInstalled = False
++        isInstalled = pkg.repo.id == 'installed'
++        return isInstalled == wantInstalled
++
+     def _do_gui_filtering(self,flt,pkg):
+         isGUI = False
+         if flt == FILTER_GUI:
+@@ -1477,32 +1516,7 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+         return isFree == wantFree
+-    def _do_basename_filtering(self,flt,pkg):
+-        if flt == FILTER_BASENAME:
+-            wantBase = True
+-        else:
+-            wantBase = False
+-
+-        isBase = self._check_basename(pkg)
+-
+-        return isBase == wantBase
+-    def _check_basename(self, pkg):
+-        '''
+-        If a package does not have a source rpm (If that ever
+-        happens), or it does have a source RPM, and the package's name
+-        is the same as the source RPM's name, then we assume it is the
+-        'base' package.
+-        '''
+-        basename = pkg.name
+-
+-        if pkg.sourcerpm:
+-            basename = rpmUtils.miscutils.splitFilename(pkg.sourcerpm)[0]
+-
+-        if basename == pkg.name:
+-            return True
+-
+-        return False
+     def _is_development_repo(self, repo):
+         if repo.endswith('-debuginfo'):
+@@ -1576,28 +1590,41 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+         '''
+         find a package based on a package id (name;version;arch;repoid)
+         '''
+-        # Split up the id
+-        (n,idver,a,d) = self.get_package_from_id(id)
+-        # get e,v,r from package id version
+-        e,v,r = self._getEVR(idver)
++        # is this an real id or just an name
++        if len(id.split(';')) > 1:
++            # Split up the id
++            (n,idver,a,d) = self.get_package_from_id(id)
++            # get e,v,r from package id version
++            e,v,r = self._getEVR(idver)
++        else:
++            n = id
++            e = v = r = a = None
+         # search the rpmdb for the nevra
+         pkgs = self.yumbase.rpmdb.searchNevra(name=n,epoch=e,ver=v,rel=r,arch=a)
+-        # if the package is found, then return it
++        # if the package is found, then return it (do not have to match the repo_id)
+         if len(pkgs) != 0:
+             return pkgs[0],True
+         # search the pkgSack for the nevra
+-        pkgs = self.yumbase.pkgSack.searchNevra(name=n,epoch=e,ver=v,rel=r,arch=a)
+-        # if the package is found, then return it
+-        if len(pkgs) != 0:
+-            return pkgs[0],False
+-        else:
++        try:
++            pkgs = self.yumbase.pkgSack.searchNevra(name=n,epoch=e,ver=v,rel=r,arch=a)
++        except yum.Errors.RepoError,e:
++            self.error(ERROR_REPO_NOT_AVAILABLE,str(e))
++        # nothing found
++        if len(pkgs) == 0:
+             return None,False
++        # one NEVRA in a single repo
++        if len(pkgs) == 1:
++            return pkgs[0],False
++        # we might have the same NEVRA in multiple repos, match by repo name
++        for pkg in pkgs:
++            if d == pkg.repoid:
++                return pkg,False
++        # repo id did not match
++        return None,False
+     def _is_inst(self,pkg):
+         return self.yumbase.rpmdb.installed(po=pkg)
+-
+-
+     def _installable(self, pkg, ematch=False):
+         """check if the package is reasonably installable, true/false"""
+@@ -1764,6 +1791,57 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+             return INFO_ENHANCEMENT
+         else:
+             return INFO_UNKNOWN
++    def _is_main_package(self,repo):
++        if repo.endswith('-debuginfo'):
++            return False
++        if repo.endswith('-devel'):
++            return False
++        if repo.endswith('-libs'):
++            return False
++        return True
++
++    def _basename_filter(self,package_list):
++        '''
++        Filter the list so that the number of packages are reduced.
++        This is done by only displaying gtk2 rather than gtk2-devel, gtk2-debuginfo, etc.
++        This imlementation is done by comparing the SRPM name, and if not falling back
++        to the first entry.
++        We have to fall back else we don't emit packages where the SRPM does not produce a
++        RPM with the same name, for instance, mono produces mono-core, mono-data and mono-winforms.
++        @package_list: a (pkg,status) list of packages
++        A new list is returned that has been filtered
++        '''
++        base_list = []
++        output_list = []
++        base_list_already_got = []
++
++        #find out the srpm name and add to a new array of compound data
++        for (pkg,status) in package_list:
++            if pkg.sourcerpm:
++                base = rpmUtils.miscutils.splitFilename(pkg.sourcerpm)[0]
++                base_list.append ((pkg,status,base,pkg.version));
++            else:
++                base_list.append ((pkg,status,'nosrpm',pkg.version));
++
++        #find all the packages that match thier basename name (done seporately so we get the "best" match)
++        for (pkg,status,base,version) in base_list:
++            if base == pkg.name and (base,version) not in base_list_already_got:
++                output_list.append((pkg,status))
++                base_list_already_got.append ((base,version))
++
++        #for all the ones not yet got, can we match against a non devel match?
++        for (pkg,status,base,version) in base_list:
++            if (base,version) not in base_list_already_got:
++                if self._is_main_package(pkg.name):
++                    output_list.append((pkg,status))
++                    base_list_already_got.append ((base,version))
++
++        #add the remainder of the packages, which should just be the single debuginfo's
++        for (pkg,status,base,version) in base_list:
++            if (base,version) not in base_list_already_got:
++                output_list.append((pkg,status))
++                base_list_already_got.append ((base,version))
++        return output_list
+     def _get_obsoleted(self,name):
+         obsoletes = self.yumbase.up.getObsoletesTuples( newest=1 )
+diff --git a/backends/zypp/pk-backend-zypp.cpp b/backends/zypp/pk-backend-zypp.cpp
+index 746da82..15c4b4f 100644
+--- a/backends/zypp/pk-backend-zypp.cpp
++++ b/backends/zypp/pk-backend-zypp.cpp
+@@ -1170,7 +1170,7 @@ backend_find_packages_thread (PkBackend *backend)
+       mode = pk_backend_get_uint (backend, "mode");
+       pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
+-      pk_backend_no_percentage_updates (backend);
++      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+       std::vector<zypp::sat::Solvable> *v = new std::vector<zypp::sat::Solvable>;
+       std::vector<zypp::sat::Solvable> *v2 = new std::vector<zypp::sat::Solvable>;
+diff --git a/client/pk-console.c b/client/pk-console.c
+index 8f69068..5a05a8e 100644
+--- a/client/pk-console.c
++++ b/client/pk-console.c
+@@ -50,7 +50,7 @@ static gboolean awaiting_space = FALSE;
+ static gboolean trusted = TRUE;
+ static guint timer_id = 0;
+ static guint percentage_last = 0;
+-static gchar *filename = NULL;
++static gchar **files_cache = NULL;
+ static PkControl *control = NULL;
+ static PkClient *client = NULL;
+ static PkClient *client_task = NULL;
+@@ -494,6 +494,12 @@ pk_console_perhaps_resolve (PkClient *client, PkFilterEnum filter, const gchar *
+               return g_strdup (package);
+       }
++      ret = pk_client_reset (client_task, error);
++      if (ret == FALSE) {
++              pk_warning ("failed to reset client task");
++              return NULL;
++      }
++
+       /* we need to resolve it */
+       ret = pk_client_resolve (client_task, filter, package, error);
+       if (ret == FALSE) {
+@@ -549,20 +555,93 @@ pk_console_perhaps_resolve (PkClient *client, PkFilterEnum filter, const gchar *
+ }
+ /**
+- * pk_console_install_package:
++ * pk_console_install_stuff:
+  **/
+ static gboolean
+-pk_console_install_package (PkClient *client, const gchar *package, GError **error)
++pk_console_install_stuff (PkClient *client, gchar **packages, GError **error)
+ {
+-      gboolean ret;
+-      gchar *package_id;
+-      package_id = pk_console_perhaps_resolve (client, PK_FILTER_ENUM_NOT_INSTALLED, package, error);
+-      if (package_id == NULL) {
+-              g_print ("%s\n", _("Could not find a package with that name to install, or package already installed"));
+-              return FALSE;
++      gboolean ret = TRUE;
++      gboolean is_local;
++      gchar *package_id = NULL;
++      gchar **package_ids = NULL;
++      gchar **files = NULL;
++      guint i;
++      guint length;
++      GPtrArray *array_packages;
++      GPtrArray *array_files;
++
++      array_packages = g_ptr_array_new ();
++      array_files = g_ptr_array_new ();
++      length = g_strv_length (packages);
++      for (i=2; i<length; i++) {
++              is_local = g_file_test (packages[i], G_FILE_TEST_EXISTS);
++              if (is_local) {
++                      g_ptr_array_add (array_files, g_strdup (packages[i]));
++              } else {
++                      package_id = pk_console_perhaps_resolve (client, PK_FILTER_ENUM_NOT_INSTALLED, packages[i], error);
++                      if (package_id == NULL) {
++                              g_print ("%s\n", _("Could not find a package with that name to install, or package already installed"));
++                              ret = FALSE;
++                              break;
++                      }
++                      g_ptr_array_add (array_packages, package_id);
++              }
+       }
+-      ret = pk_client_install_package (client, package_id, error);
+-      g_free (package_id);
++
++      /* one of the resolves failed */
++      if (!ret) {
++              pk_warning ("resolve failed");
++              goto out;
++      }
++
++
++      /* any to process? */
++      if (array_packages->len > 0) {
++              /* convert to strv */
++              package_ids = pk_ptr_array_to_argv (array_packages);
++
++              /* reset */
++              ret = pk_client_reset (client, error);
++              if (!ret) {
++                      pk_warning ("failed to reset");
++                      goto out;
++              }
++
++              ret = pk_client_install_package (client, package_id, error);
++              if (!ret) {
++                      pk_warning ("failed to install packages");
++                      goto out;
++              }
++      }
++
++      /* any to process? */
++      if (array_files->len > 0) {
++              /* convert to strv */
++              files = pk_ptr_array_to_argv (array_files);
++
++              /* save for untrusted callback */
++              g_strfreev (files_cache);
++              files_cache = g_strdupv (files);
++
++              /* reset */
++              ret = pk_client_reset (client, error);
++              if (!ret) {
++                      pk_warning ("failed to reset");
++                      goto out;
++              }
++
++              ret = pk_client_install_files (client, trusted, files, error);
++              if (!ret) {
++                      pk_warning ("failed to install files");
++                      goto out;
++              }
++      }
++
++out:
++      g_strfreev (package_ids);
++      g_strfreev (files);
++      g_ptr_array_free (array_files, TRUE);
++      g_ptr_array_free (array_packages, TRUE);
+       return ret;
+ }
+@@ -570,16 +649,16 @@ pk_console_install_package (PkClient *client, const gchar *package, GError **err
+  * pk_console_remove_only:
+  **/
+ static gboolean
+-pk_console_remove_only (PkClient *client, const gchar *package_id, gboolean force, gboolean autoremove, GError **error)
++pk_console_remove_only (PkClient *client, gchar **package_ids, gboolean force, GError **error)
+ {
+       gboolean ret;
+-      pk_debug ("remove %s", package_id);
++      pk_debug ("remove+ %s", package_ids[0]);
+       ret = pk_client_reset (client, error);
+       if (!ret) {
+               return ret;
+       }
+-      return pk_client_remove_package (client, package_id, force, autoremove, error);
++      return pk_client_remove_packages (client, package_ids, force, FALSE, error);
+ }
+ /**
+@@ -625,64 +704,99 @@ pk_console_get_prompt (const gchar *question, gboolean defaultyes)
+ }
+ /**
+- * pk_console_remove_package:
++ * pk_console_remove_packages:
+  **/
+ static gboolean
+-pk_console_remove_package (PkClient *client, const gchar *package, GError **error)
++pk_console_remove_packages (PkClient *client, gchar **packages, GError **error)
+ {
+       gchar *package_id;
+-      gboolean ret;
+-      guint length;
++      gboolean ret = TRUE;
+       PkPackageItem *item;
+       PkPackageId *ident;
+-      guint i;
++      guint i, j;
++      guint size;
++      guint length;
+       gboolean remove;
++      GPtrArray *array;
++      gchar **package_ids = NULL;
++      PkPackageList *list;
++
++      array = g_ptr_array_new ();
++      list = pk_package_list_new ();
++      length = g_strv_length (packages);
++      for (i=2; i<length; i++) {
++              package_id = pk_console_perhaps_resolve (client, PK_FILTER_ENUM_INSTALLED, packages[i], error);
++              if (package_id == NULL) {
++                      g_print ("%s:%s\n", _("Could not find a package to remove"), packages[i]);
++                      ret = FALSE;
++                      break;
++              }
++              g_ptr_array_add (array, g_strdup (package_id));
++              pk_debug ("resolved to %s", package_id);
++              g_free (package_id);
++      }
+-      package_id = pk_console_perhaps_resolve (client, PK_FILTER_ENUM_INSTALLED, package, error);
+-      if (package_id == NULL) {
+-              g_print ("%s\n", _("Could not find a package with that name to remove"));
+-              return FALSE;
++      /* one of the resolves failed */
++      if (!ret) {
++              goto out;
+       }
++      /* convert to strv */
++      package_ids = pk_ptr_array_to_argv (array);
++
+       /* are we dumb and can't check for requires? */
+       if (!pk_enums_contain (roles, PK_ROLE_ENUM_GET_REQUIRES)) {
+               /* no, just try to remove it without deps */
+-              ret = pk_console_remove_only (client, package_id, FALSE, FALSE, error);
+-              g_free (package_id);
+-              return ret;
++              ret = pk_console_remove_only (client, package_ids, FALSE, error);
++              goto out;
+       }
+-      /* see if any packages require this one */
+-      ret = pk_client_reset (client_task, error);
+-      if (!ret) {
+-              pk_warning ("failed to reset");
+-              return FALSE;
++      /* get the requires packages for each package_id */
++      length = g_strv_length (package_ids);
++      for (i=0; i<length; i++) {
++              ret = pk_client_reset (client_task, error);
++              if (!ret) {
++                      pk_warning ("failed to reset");
++                      break;
++              }
++
++              pk_debug ("Getting installed requires for %s", package_ids[i]);
++              /* see if any packages require this one */
++              ret = pk_client_get_requires (client_task, PK_FILTER_ENUM_INSTALLED, package_ids[i], TRUE, error);
++              if (!ret) {
++                      pk_warning ("failed to get requires");
++                      break;
++              }
++
++              /* see how many packages there are */
++              size = pk_client_package_buffer_get_size (client_task);
++              for (j=0; j<size; j++) {
++                      item = pk_client_package_buffer_get_item (client_task, j);
++                      pk_package_list_add_item (list, item);
++              }
+       }
+-      pk_debug ("Getting installed requires for %s", package_id);
+-      ret = pk_client_get_requires (client_task, PK_FILTER_ENUM_INSTALLED, package_id, TRUE, error);
++      /* one of the get-requires failed */
+       if (!ret) {
+-              return FALSE;
++              goto out;
+       }
+-      /* see how many packages there are */
+-      length = pk_client_package_buffer_get_size (client_task);
+-
+       /* if there are no required packages, just do the remove */
++      length = pk_package_list_get_size (list);
+       if (length == 0) {
+               pk_debug ("no requires");
+-              ret = pk_console_remove_only (client, package_id, FALSE, FALSE, error);
+-              g_free (package_id);
+-              return ret;
++              ret = pk_console_remove_only (client, package_ids, FALSE, error);
++              goto out;
+       }
++
+       /* present this to the user */
+       if (awaiting_space) {
+               g_print ("\n");
+       }
+       g_print ("%s:\n", _("The following packages have to be removed"));
+       for (i=0; i<length; i++) {
+-              item = pk_client_package_buffer_get_item (client_task, i);
++              item = pk_package_list_get_item (list, i);
+               ident = pk_package_id_new_from_string (item->package_id);
+               g_print ("%i\t%s-%s\n", i, ident->name, ident->version);
+               pk_package_id_free (ident);
+@@ -694,14 +808,17 @@ pk_console_remove_package (PkClient *client, const gchar *package, GError **erro
+       /* we chickened out */
+       if (remove == FALSE) {
+               g_print ("%s\n", _("Cancelled!"));
+-              g_free (package_id);
+-              return FALSE;
++              ret = FALSE;
++              goto out;
+       }
+       /* remove all the stuff */
+-      ret = pk_console_remove_only (client, package_id, TRUE, FALSE, error);
+-      g_free (package_id);
++      ret = pk_console_remove_only (client, package_ids, TRUE, error);
++out:
++      g_object_unref (list);
++      g_strfreev (package_ids);
++      g_ptr_array_free (array, TRUE);
+       return ret;
+ }
+@@ -840,7 +957,7 @@ pk_console_error_code_cb (PkClient *client, PkErrorCodeEnum error_code, const gc
+           error_code == PK_ERROR_ENUM_MISSING_GPG_SIGNATURE && trusted) {
+               pk_debug ("need to try again with trusted FALSE");
+               trusted = FALSE;
+-              ret = pk_client_install_file (client_install_files, trusted, filename, &error);
++              ret = pk_client_install_files (client_install_files, trusted, files_cache, &error);
+               /* we succeeded, so wait for the requeue */
+               if (!ret) {
+                       pk_warning ("failed to install file second time: %s", error->message);
+@@ -1153,7 +1270,6 @@ main (int argc, char *argv[])
+       const gchar *value = NULL;
+       const gchar *details = NULL;
+       const gchar *parameter = NULL;
+-      PkRoleEnum roles;
+       PkGroupEnum groups;
+       gchar *text;
+       ret = FALSE;
+@@ -1324,15 +1440,7 @@ main (int argc, char *argv[])
+                       g_print (_("You need to specify a package or file to install"));
+                       goto out;
+               }
+-              /* is it a local file? */
+-              ret = g_file_test (value, G_FILE_TEST_EXISTS);
+-              if (ret) {
+-                      ret = pk_client_install_file (client, trusted, value, &error);
+-                      /* we need this for the untrusted try */
+-                      filename = g_strdup (value);
+-              } else {
+-                      ret = pk_console_install_package (client, value, &error);
+-              }
++              ret = pk_console_install_stuff (client, argv, &error);
+       } else if (strcmp (mode, "install-sig") == 0) {
+               if (value == NULL || details == NULL || parameter == NULL) {
+@@ -1346,7 +1454,7 @@ main (int argc, char *argv[])
+                       g_print (_("You need to specify a package to remove"));
+                       goto out;
+               }
+-              ret = pk_console_remove_package (client, value, &error);
++              ret = pk_console_remove_packages (client, argv, &error);
+       } else if (strcmp (mode, "accept-eula") == 0) {
+               if (value == NULL) {
+@@ -1465,9 +1573,9 @@ main (int argc, char *argv[])
+               ret = pk_client_get_packages (client, filters, &error);
+       } else if (strcmp (mode, "get-actions") == 0) {
+-              roles = pk_control_get_actions (control);
+               text = pk_role_enums_to_text (roles);
+-              g_print ("roles=%s\n", text);
++              g_strdelimit (text, ";", '\n');
++              g_print ("%s\n", text);
+               g_free (text);
+               maybe_sync = FALSE;
+               /* these can never fail */
+@@ -1476,7 +1584,8 @@ main (int argc, char *argv[])
+       } else if (strcmp (mode, "get-filters") == 0) {
+               filters = pk_control_get_filters (control);
+               text = pk_filter_enums_to_text (filters);
+-              g_print ("filters=%s\n", text);
++              g_strdelimit (text, ";", '\n');
++              g_print ("%s\n", text);
+               g_free (text);
+               maybe_sync = FALSE;
+               /* these can never fail */
+@@ -1485,7 +1594,8 @@ main (int argc, char *argv[])
+       } else if (strcmp (mode, "get-groups") == 0) {
+               groups = pk_control_get_groups (control);
+               text = pk_group_enums_to_text (groups);
+-              g_print ("groups=%s\n", text);
++              g_strdelimit (text, ";", '\n');
++              g_print ("%s\n", text);
+               g_free (text);
+               maybe_sync = FALSE;
+               /* these can never fail */
+@@ -1525,7 +1635,7 @@ out:
+       g_free (options_help);
+       g_free (filter);
+       g_free (summary);
+-      g_free (filename);
++      g_strfreev (files_cache);
+       g_object_unref (control);
+       g_object_unref (client);
+       g_object_unref (client_task);
+diff --git a/configure.ac b/configure.ac
+index 9d734e1..f614d2b 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -535,7 +535,7 @@ if test x$enable_box = xyes; then
+ fi
+ if test x$enable_opkg = xyes; then
+-      PKG_CHECK_MODULES(OPKG, libopkg = 0.1.3)
++      PKG_CHECK_MODULES(OPKG, libopkg = 0.1.4)
+       AC_SUBST(OPKG_CFLAGS)
+       AC_SUBST(OPKG_LIBS)
+ fi
+diff --git a/contrib/yum-packagekit/refresh-packagekit.py b/contrib/yum-packagekit/refresh-packagekit.py
+index 9c0bdf4..b440539 100644
+--- a/contrib/yum-packagekit/refresh-packagekit.py
++++ b/contrib/yum-packagekit/refresh-packagekit.py
+@@ -35,7 +35,7 @@ def posttrans_hook(conduit):
+                                           '/org/freedesktop/PackageKit')
+         packagekit_iface = dbus.Interface(packagekit_proxy, 'org.freedesktop.PackageKit')
+         packagekit_iface.StateHasChanged('posttrans')
+-    except dbus.DBusException, e:
++    except Exception, e:
+         conduit.info(2, "Unable to send message to PackageKit")
+         conduit.info(6, "%s" %(e,))
+diff --git a/data/tests/Makefile.am b/data/tests/Makefile.am
+index d15dd6c..6935e66 100644
+--- a/data/tests/Makefile.am
++++ b/data/tests/Makefile.am
+@@ -5,6 +5,7 @@ NULL =
+ TEST_FILES =                                          \
+       pk-spawn-test.sh                                \
++      pk-spawn-proxy.sh                               \
+       pk-spawn-test-sigquit.sh                        \
+       pk-spawn-test-profiling.sh                      \
+       $(NULL)
+diff --git a/data/tests/pk-spawn-proxy.sh b/data/tests/pk-spawn-proxy.sh
+new file mode 100755
+index 0000000..57774f1
+--- /dev/null
++++ b/data/tests/pk-spawn-proxy.sh
+@@ -0,0 +1,20 @@
++#!/bin/bash
++# Copyright (C) 2008 Richard Hughes <richard@hughsie.com>
++# Licensed under the GNU General Public License Version 2
++# 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 2 of the License, or
++# (at your option) any later version.
++
++if [ -z "${http_proxy}" ]; then
++      echo "no http proxy"
++      exit 1
++fi
++
++if [ -z "${ftp_proxy}" ]; then
++      echo "no ftp proxy"
++      exit 1
++fi
++
++echo -e "percentage\t100"
++
+diff --git a/docs/html/index.html b/docs/html/index.html
+index 7270eb7..d60f825 100644
+--- a/docs/html/index.html
++++ b/docs/html/index.html
+@@ -9,9 +9,9 @@
+ <table align="center" class="title">
+ <tr>
+- <td><img src="img/packagekit.png" alt="[img]"/></td>
++ <td><img src="img/packagekit.png" alt=""/></td>
+  <td width="95%" valign="middle"><p class="title">PackageKit Main Page</p></td>
+- <td><img src="img/packagekit.png" alt="[img]"/></td>
++ <td><img src="img/packagekit.png" alt=""/></td>
+ </tr>
+ </table>
+@@ -20,10 +20,10 @@
+ <table align="center" cellpadding="5px" border="0">
+ <tr>
+- <td align="center"><a href="pk-intro.html"><img src="img/large-accessories-text-editor.png" width="128" alt="[img]"/></a></td>
+- <td align="center"><a href="pk-using.html"><img src="img/large-preferences-system.png" width="128" alt="[img]"/></a></td>
+- <td align="center"><a href="pk-download.html"><img src="img/large-dialog-information.png" width="128" alt="[img]"/></a></td>
+- <td align="center"><a href="pk-screenshots.html"><img src="img/large-emblem-photos.png" width="128" alt="[img]"/></a></td>
++ <td align="center"><a href="pk-intro.html"><img src="img/large-accessories-text-editor.png" width="128" alt=""/></a></td>
++ <td align="center"><a href="pk-using.html"><img src="img/large-preferences-system.png" width="128" alt=""/></a></td>
++ <td align="center"><a href="pk-download.html"><img src="img/large-dialog-information.png" width="128" alt=""/></a></td>
++ <td align="center"><a href="pk-screenshots.html"><img src="img/large-emblem-photos.png" width="128" alt=""/></a></td>
+ </tr>
+ <tr>
+  <td><p class="indextitle"><a href="pk-intro.html" class="indextitle">What is<br/>PackageKit?</a></p></td>
+@@ -32,10 +32,10 @@
+  <td><p class="indextitle"><a href="pk-screenshots.html" class="indextitle">Screenshots</a></p></td>
+ </tr>
+ <tr>
+- <td align="center"><a href="pk-authors.html"><img src="img/large-authors.png" width="128" alt="[img]"/></a></td>
+- <td align="center"><a href="pk-bugs.html"><img src="img/large-applications-development.png" width="128" alt="[img]"/></a></td>
+- <td align="center"><a href="pk-help.html"><img src="img/large-system-users.png" width="128" alt="[img]"/></a></td>
+- <td align="center"><a href="pk-faq.html"><img src="img/large-help-browser.png" width="128" alt="[img]"/></a></td>
++ <td align="center"><a href="pk-authors.html"><img src="img/large-authors.png" width="128" alt=""/></a></td>
++ <td align="center"><a href="pk-bugs.html"><img src="img/large-applications-development.png" width="128" alt=""/></a></td>
++ <td align="center"><a href="pk-help.html"><img src="img/large-system-users.png" width="128" alt=""/></a></td>
++ <td align="center"><a href="pk-faq.html"><img src="img/large-help-browser.png" width="128" alt=""/></a></td>
+ </tr>
+ <tr>
+  <td><p class="indextitle"><a href="pk-authors.html" class="indextitle">Who develops<br/>PackageKit?</a></p></td>
+diff --git a/docs/html/pk-authors.html b/docs/html/pk-authors.html
+index 08289ad..607a7a4 100644
+--- a/docs/html/pk-authors.html
++++ b/docs/html/pk-authors.html
+@@ -9,9 +9,9 @@
+ <table align="center" class="title">
+ <tr>
+- <td><img src="img/packagekit.png" alt="[img]"/></td>
++ <td><img src="img/packagekit.png" alt=""/></td>
+  <td width="95%" valign="middle"><p class="title">Who develops PackageKit?</p></td>
+- <td><img src="img/packagekit.png" alt="[img]"/></td>
++ <td><img src="img/packagekit.png" alt=""/></td>
+ </tr>
+ </table>
+@@ -22,7 +22,7 @@
+ <table cellpadding="10">
+ <tr>
+  <td>
+-  <img src="img/author-hughsie.png" alt="[img]"/><!-- image should be 120px wide -->
++  <img src="img/author-hughsie.png" alt=""/><!-- image should be 120px wide -->
+  </td>
+  <td>
+   <h2>Richard Hughes</h2>
+@@ -48,7 +48,7 @@
+ <tr>
+  <td>
+-  <img src="img/author-kenvandine.png" alt="[img]"/><!-- image should be 120px wide -->
++  <img src="img/author-kenvandine.png" alt=""/><!-- image should be 120px wide -->
+  </td>
+  <td>
+   <h2>Ken VanDine</h2>
+@@ -66,7 +66,7 @@
+ <tr>
+  <td>
+-  <img src="img/author-btimothy.png" alt="[img]"/><!-- image should be 120px wide -->
++  <img src="img/author-btimothy.png" alt=""/><!-- image should be 120px wide -->
+  </td>
+  <td>
+   <h2>Boyd Timothy</h2>
+@@ -84,7 +84,7 @@
+ <tr>
+  <td>
+-  <img src="img/author-rnorwood.png" alt="[img]"/><!-- image should be 120px wide -->
++  <img src="img/author-rnorwood.png" alt=""/><!-- image should be 120px wide -->
+  </td>
+  <td>
+   <h2>Robin Norwood</h2>
+@@ -101,7 +101,7 @@
+ <tr>
+  <td>
+-  <img src="img/author-tomparker.png" alt="[img]"/><!-- image should be 120px wide -->
++  <img src="img/author-tomparker.png" alt=""/><!-- image should be 120px wide -->
+  </td>
+  <td>
+   <h2>Tom Parker</h2>
+@@ -118,7 +118,7 @@
+ <tr>
+  <td>
+-  <img src="img/author-timlau.png" alt="[img]"/><!-- image should be 120px wide -->
++  <img src="img/author-timlau.png" alt=""/><!-- image should be 120px wide -->
+  </td>
+  <td>
+   <h2>Tim Lauridsen</h2>
+@@ -139,7 +139,7 @@
+ <tr>
+  <td>
+-  <img src="img/author-lmacken.png" alt="[img]"/>
++  <img src="img/author-lmacken.png" alt=""/>
+  </td>
+  <td>
+   <h2>Luke Macken</h2>
+@@ -154,7 +154,7 @@
+ <tr>
+  <td>
+-  <img src="img/author-grzegorzdabrowski.png" alt="[img]"/><!-- image should be 120px wide -->
++  <img src="img/author-grzegorzdabrowski.png" alt=""/><!-- image should be 120px wide -->
+  </td>
+  <td>
+   <h2>Grzegorz Dąbrowski</h2>
+@@ -173,7 +173,7 @@
+ <tr>
+  <td>
+-  <img src="img/author-caglar.png" alt="[img]"/><!-- image should be 120px wide -->
++  <img src="img/author-caglar.png" alt=""/><!-- image should be 120px wide -->
+  </td>
+  <td>
+   <h2>S.Çağlar Onur</h2>
+@@ -195,7 +195,7 @@
+ <tr>
+  <td>
+-  <img src="img/author-elliot.png" alt="[img]"/>
++  <img src="img/author-elliot.png" alt=""/>
+  </td>
+  <td>
+   <h2>Elliot Peele</h2>
+@@ -210,7 +210,7 @@
+ <tr>
+  <td>
+-  <img src="img/author-jbowes.png" alt="[img]"/><!-- image should be 120px wide -->
++  <img src="img/author-jbowes.png" alt=""/><!-- image should be 120px wide -->
+  </td>
+  <td>
+   <h2>James Bowes</h2>
+@@ -227,7 +227,7 @@
+ <tr>
+  <td>
+-  <img src="img/author-unknown.png" alt="[img]"/><!-- image should be 120px wide -->
++  <img src="img/author-unknown.png" alt=""/><!-- image should be 120px wide -->
+  </td>
+  <td>
+   <h2>Thomas Wood</h2>
+@@ -247,7 +247,7 @@
+ <tr>
+  <td>
+-  <img src="img/author-unknown.png" alt="[img]"/><!-- image should be 120px wide -->
++  <img src="img/author-unknown.png" alt=""/><!-- image should be 120px wide -->
+  </td>
+  <td>
+   <h2>Scott Reeves</h2>
+diff --git a/docs/html/pk-bugs.html b/docs/html/pk-bugs.html
+index 89f7c48..2ee12ea 100644
+--- a/docs/html/pk-bugs.html
++++ b/docs/html/pk-bugs.html
+@@ -9,9 +9,9 @@
+ <table align="center" class="title">
+ <tr>
+- <td><img src="img/packagekit.png" alt="[img]"/></td>
++ <td><img src="img/packagekit.png" alt=""/></td>
+  <td width="95%" valign="middle"><p class="title">Reporting Bugs</p></td>
+- <td><img src="img/packagekit.png" alt="[img]"/></td>
++ <td><img src="img/packagekit.png" alt=""/></td>
+ </tr>
+ </table>
+diff --git a/docs/html/pk-download.html b/docs/html/pk-download.html
+index 6f796b8..0cdc85c 100644
+--- a/docs/html/pk-download.html
++++ b/docs/html/pk-download.html
+@@ -9,9 +9,9 @@
+ <table align="center" class="title">
+ <tr>
+- <td><img src="img/packagekit.png" alt="[img]"/></td>
++ <td><img src="img/packagekit.png" alt=""/></td>
+  <td width="95%" valign="middle"><p class="title">Where can I download it?</p></td>
+- <td><img src="img/packagekit.png" alt="[img]"/></td>
++ <td><img src="img/packagekit.png" alt=""/></td>
+ </tr>
+ </table>
+diff --git a/docs/html/pk-faq.html b/docs/html/pk-faq.html
+index a25e2b7..efa8344 100644
+--- a/docs/html/pk-faq.html
++++ b/docs/html/pk-faq.html
+@@ -9,9 +9,9 @@
+ <table align="center" class="title">
+ <tr>
+- <td><center><img src="img/packagekit.png" alt="[img]"/></center></td>
++ <td><center><img src="img/packagekit.png" alt=""/></center></td>
+  <td width="95%" valign="middle"><p class="title">Frequently Asked Questions</p></td>
+- <td><center><img src="img/packagekit.png" alt="[img]"/></center></td>
++ <td><center><img src="img/packagekit.png" alt=""/></center></td>
+ </tr>
+ </table>
+@@ -22,6 +22,7 @@
+ <h2>Table Of Contents</h2>
+ <ul>
+ <li><a href="#how-complete">How complete are the backends?</a></li>
++<li><a href="#run-as-root">When run as root, gpk-application and pkcon do not work!</a></li>
+ <li><a href="#session-system">Why is there a session service and and a system service?</a></li>
+ <li><a href="#session-methods">How do I use PackageKit in my application?</a></li>
+ <li><a href="#rawhide-updates">Why don't I get update details with Fedora Rawhide?</a></li>
+@@ -565,6 +566,19 @@
+ </table>
+ <hr>
++<h3><a name="run-as-root">When run as root, <code>gpk-application</code> and <code>pkcon</code> do not work!</a></h3>
++<p>
++GTK+ tools should not be run as the root user, <b>PERIOD</b>.
++Any GTK+ program run as the root user is a massive security hole -- GTK+ just isn't designed with
++this in mind.
++There are <b>numerous</b> attack vectors when running as root, and programs shouldn't do such
++insane and insecure things.
++</p>
++<p>
++Please see <a href="http://www.gtk.org/setuid.html">the GTK+ explanation</a> for more rationale.
++</p>
++
++<hr>
+ <h3><a name="session-system">Why is there a session service <b>and</b> and a system service?</a></h3>
+ <p>
+ PackageKit runs a process <code>packagekitd</code> that is a daemon that runs per-system.
+diff --git a/docs/html/pk-help.html b/docs/html/pk-help.html
+index 5b44d50..5bc7827 100644
+--- a/docs/html/pk-help.html
++++ b/docs/html/pk-help.html
+@@ -9,9 +9,9 @@
+ <table align="center" class="title">
+ <tr>
+- <td><img src="img/packagekit.png" alt="[img]"/></td>
++ <td><img src="img/packagekit.png" alt=""/></td>
+  <td width="95%" valign="middle"><p class="title">How can I help?</p></td>
+- <td><img src="img/packagekit.png" alt="[img]"/></td>
++ <td><img src="img/packagekit.png" alt=""/></td>
+ </tr>
+ </table>
+@@ -72,9 +72,9 @@ as for instructions!
+ <b>0.2.2</b> - To be released June 2008
+ </p>
+ <ul>
+-<li>Multiple package install and remove from pkcon <i>(0%)</i></li>
++<li>Network proxy server support <i>(70%)</i></li>
++<li>Multiple package install and remove from pkcon <i>(80%)</i></li>
+ <li>NetworkManager integration so we can detect GPRS (and modem) connections. <i>(10%)</i></li>
+-<li>Filter for source packages. <i>(0%)</i></li>
+ </ul>
+ <p>
+ <b>0.2.3</b> - To be released July 2008
+@@ -84,6 +84,12 @@ as for instructions!
+ <li>Multiple package installs from gpk-application <i>(0%)</i></li>
+ <li>Ignoring packages from the update viewer per-session <i>(10%)</i></li>
+ </ul>
++<p>
++<b>0.3.0</b> - To be released December 2008
++</p>
++<ul>
++<li>More composite types <code>s</code> to <code>as</code> <i>(0%)</i></li>
++</ul>
+ <p>Back to the <a href="index.html">main page</a></p>
+diff --git a/docs/html/pk-intro.html b/docs/html/pk-intro.html
+index c42be21..64f72fc 100644
+--- a/docs/html/pk-intro.html
++++ b/docs/html/pk-intro.html
+@@ -9,9 +9,9 @@
+ <table align="center" class="title">
+ <tr>
+- <td><img src="img/packagekit.png" alt="[img]"/></td>
++ <td><img src="img/packagekit.png" alt=""/></td>
+  <td width="95%" valign="middle"><p class="title">What is PackageKit?</p></td>
+- <td><img src="img/packagekit.png" alt="[img]"/></td>
++ <td><img src="img/packagekit.png" alt=""/></td>
+ </tr>
+ </table>
+diff --git a/docs/html/pk-screenshots.html b/docs/html/pk-screenshots.html
+index 78bd01f..5c7d4fa 100644
+--- a/docs/html/pk-screenshots.html
++++ b/docs/html/pk-screenshots.html
+@@ -9,9 +9,9 @@
+ <table align="center" class="title">
+ <tr>
+- <td><center><img src="img/packagekit.png" alt="[img]"/></center></td>
++ <td><center><img src="img/packagekit.png" alt=""/></center></td>
+  <td width="95%" valign="middle"><p class="title">Screenshots</p></td>
+- <td><center><img src="img/packagekit.png" alt="[img]"/></center></td>
++ <td><center><img src="img/packagekit.png" alt=""/></center></td>
+ </tr>
+ </table>
+@@ -26,77 +26,77 @@
+ <h1><a name="gnome">GNOME Screenshots</a></h1>
+-<center><img src="img/gpk-application-search.png" alt="[img]"/></center>
++<center><img src="img/gpk-application-search.png" alt=""/></center>
+ <p class="caption">Add/Remove Software search</p>
+-<center><img src="img/gpk-application-groups.png" alt="[img]"/></center>
++<center><img src="img/gpk-application-groups.png" alt=""/></center>
+ <p class="caption">Add/Remove Software groups</p>
+-<center><img src="img/gpk-log.png" alt="[img]"/></center>
++<center><img src="img/gpk-log.png" alt=""/></center>
+ <p class="caption">Transaction viewer</p>
+-<center><img src="img/gpk-updates-overview.png" alt="[img]"/></center>
++<center><img src="img/gpk-updates-overview.png" alt=""/></center>
+ <p class="caption">Update viewer overview</p>
+-<center><img src="img/gpk-updates.png" alt="[img]"/></center>
++<center><img src="img/gpk-updates.png" alt=""/></center>
+ <p class="caption">Update viewer</p>
+-<center><img src="img/gpk-prefs.png" alt="[img]"/></center>
++<center><img src="img/gpk-prefs.png" alt=""/></center>
+ <p class="caption">Auto update preferences</p>
+-<center><img src="img/gpk-progress.png" alt="[img]"/></center>
++<center><img src="img/gpk-progress.png" alt=""/></center>
+ <p class="caption">Progress dialog</p>
+-<center><img src="img/gpk-added-deps.png" alt="[img]"/></center>
++<center><img src="img/gpk-added-deps.png" alt=""/></center>
+ <p class="caption">Added check warning</p>
+-<center><img src="img/gpk-eula.png" alt="[img]"/></center>
++<center><img src="img/gpk-eula.png" alt=""/></center>
+ <p class="caption">EULA dialog</p>
+-<center><img src="img/gpk-remove-confirm.png" alt="[img]"/></center>
++<center><img src="img/gpk-remove-confirm.png" alt=""/></center>
+ <p class="caption">Remove check warning</p>
+-<center><img src="img/gpk-repo-auth.png" alt="[img]"/></center>
++<center><img src="img/gpk-repo-auth.png" alt=""/></center>
+ <p class="caption">Repository authentication</p>
+-<center><img src="img/gpk-repo.png" alt="[img]"/></center>
++<center><img src="img/gpk-repo.png" alt=""/></center>
+ <p class="caption">Repository viewer</p>
+-<center><img src="img/gpk-backend-status.png" alt="[img]"/></center>
++<center><img src="img/gpk-backend-status.png" alt=""/></center>
+ <p class="caption">PackageKit backend status</p>
+-<center><img src="img/gpk-updates-warning.png" alt="[img]"/></center>
++<center><img src="img/gpk-updates-warning.png" alt=""/></center>
+ <p class="caption">Libnotify updates warning</p>
+-<center><img src="img/gpk-waiting.png" alt="[img]"/></center>
++<center><img src="img/gpk-waiting.png" alt=""/></center>
+ <p class="caption">Tasks waiting</p>
+-<center><img src="img/gpk-battery.png" alt="[img]"/></center>
++<center><img src="img/gpk-battery.png" alt=""/></center>
+ <p class="caption">Intergration with gnome-power-manager</p>
+-<center><img src="img/gpk-inhibit.png" alt="[img]"/></center>
++<center><img src="img/gpk-inhibit.png" alt=""/></center>
+ <p class="caption">Inhibit with gnome-power-manager</p>
+-<center><img src="img/gpk-require-restart.png" alt="[img]"/></center>
++<center><img src="img/gpk-require-restart.png" alt=""/></center>
+ <p class="caption">We sometimes need to do a restart</p>
+-<center><img src="img/gpk-auto-update.png" alt="[img]"/></center>
++<center><img src="img/gpk-auto-update.png" alt=""/></center>
+ <p class="caption">Auto update install dialog</p>
+ <h1><a name="kde">KDE Screenshots</a></h1>
+-<center><img src="img/kpk-search.png" alt="[img]"/></center>
++<center><img src="img/kpk-search.png" alt=""/></center>
+ <p class="caption">KPackageKit Searching</p>
+-<center><img src="img/kpk-information.png" alt="[img]"/></center>
++<center><img src="img/kpk-information.png" alt=""/></center>
+ <p class="caption">KPackageKit Package Information</p>
+-<center><img src="img/pk-opensuse-updater.png" alt="[img]"/></center>
++<center><img src="img/pk-opensuse-updater.png" alt=""/></center>
+ <p class="caption">OpenSuse Updater</p>
+ <h1><a name="moko">OpenMoko Screenshots</a></h1>
+-<center><img src="img/assassin.png" alt="[img]"/></center>
++<center><img src="img/assassin.png" alt=""/></center>
+ <p class="caption">Assassin</p>
+ <p>Back to the <a href="index.html">main page</a></p>
+diff --git a/docs/html/pk-using.html b/docs/html/pk-using.html
+index cc455c7..b2b028e 100644
+--- a/docs/html/pk-using.html
++++ b/docs/html/pk-using.html
+@@ -9,9 +9,9 @@
+ <table align="center" class="title">
+ <tr>
+- <td><img src="img/packagekit.png" alt="[img]"/></td>
++ <td><img src="img/packagekit.png" alt=""/></td>
+  <td width="95%" valign="middle"><p class="title">How do I use PackageKit?</p></td>
+- <td><img src="img/packagekit.png" alt="[img]"/></td>
++ <td><img src="img/packagekit.png" alt=""/></td>
+ </tr>
+ </table>
+diff --git a/docs/spec/pk-concepts.xml b/docs/spec/pk-concepts.xml
+index 312c5a4..0b75b10 100644
+--- a/docs/spec/pk-concepts.xml
++++ b/docs/spec/pk-concepts.xml
+@@ -127,6 +127,13 @@
+               This allows the used to choose non-native packages if a multi-lib policy is allowed.
+             </entry>
+           </row>
++          <row>
++            <entry><literal>source</literal> or <literal>~source</literal></entry>
++            <entry>
++              The source filter will only return source packages.
++              These are typically useful when rebuilding other packages.
++            </entry>
++          </row>
+         </tbody>
+       </tgroup>
+     </informaltable>
+diff --git a/etc/PackageKit.conf.in b/etc/PackageKit.conf.in
+index a6af99b..8f9bd57 100644
+--- a/etc/PackageKit.conf.in
++++ b/etc/PackageKit.conf.in
+@@ -31,3 +31,13 @@ ShutdownTimeout=300
+ # default=@defaultbackend@
+ DefaultBackend=@defaultbackend@
++# Proxy settings, uncomment as required
++#
++# NOTE: PackageKit does not use these settings, they are passed to backends.
++# Backends may ignore these values, or they may be updated from the session.
++#
++# They are in the format username:password@server:port
++#
++# ProxyHTTP=username:password@server.lan:8080
++# ProxyFTP=username:password@server.lan:21
++
+diff --git a/libpackagekit/Makefile.am b/libpackagekit/Makefile.am
+index 6b8c6b8..aeafe44 100644
+--- a/libpackagekit/Makefile.am
++++ b/libpackagekit/Makefile.am
+@@ -37,6 +37,7 @@ libpackagekit_include_HEADERS =                                      \
+       pk-connection.h                                         \
+       pk-package-id.h                                         \
+       pk-package-ids.h                                        \
++      pk-package-item.h                                       \
+       pk-package-list.h                                       \
+       pk-enum.h                                               \
+       pk-common.h                                             \
+@@ -59,6 +60,8 @@ libpackagekit_la_SOURCES =                                   \
+       pk-package-id.h                                         \
+       pk-package-ids.c                                        \
+       pk-package-ids.h                                        \
++      pk-package-item.c                                       \
++      pk-package-item.h                                       \
+       pk-package-list.c                                       \
+       pk-package-list.h                                       \
+       pk-enum.h                                               \
+diff --git a/libpackagekit/pk-enum.c b/libpackagekit/pk-enum.c
+index b5b6ac3..5743dcb 100644
+--- a/libpackagekit/pk-enum.c
++++ b/libpackagekit/pk-enum.c
+@@ -193,6 +193,8 @@ static PkEnumMatch enum_filter[] = {
+       {PK_FILTER_ENUM_NOT_NEWEST,             "~newest"},
+       {PK_FILTER_ENUM_ARCH,                   "arch"},
+       {PK_FILTER_ENUM_NOT_ARCH,               "~arch"},
++      {PK_FILTER_ENUM_SOURCE,                 "source"},
++      {PK_FILTER_ENUM_NOT_SOURCE,             "~source"},
+       {0, NULL}
+ };
+diff --git a/libpackagekit/pk-enum.h b/libpackagekit/pk-enum.h
+index 33e8a91..e616b64 100644
+--- a/libpackagekit/pk-enum.h
++++ b/libpackagekit/pk-enum.h
+@@ -182,7 +182,9 @@ typedef enum {
+       PK_FILTER_ENUM_NOT_NEWEST               = 1 << 15,
+       PK_FILTER_ENUM_ARCH                     = 1 << 16,
+       PK_FILTER_ENUM_NOT_ARCH                 = 1 << 17,
+-      PK_FILTER_ENUM_UNKNOWN                  = 1 << 18
++      PK_FILTER_ENUM_SOURCE                   = 1 << 18,
++      PK_FILTER_ENUM_NOT_SOURCE               = 1 << 19,
++      PK_FILTER_ENUM_UNKNOWN                  = 1 << 20
+ } PkFilterEnum;
+ /**
+diff --git a/libpackagekit/pk-package-item.c b/libpackagekit/pk-package-item.c
+new file mode 100644
+index 0000000..87905dc
+--- /dev/null
++++ b/libpackagekit/pk-package-item.c
+@@ -0,0 +1,190 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
++ *
++ * Copyright (C) 2007-2008 Richard Hughes <richard@hughsie.com>
++ *
++ * Licensed under the GNU General Public License Version 2
++ *
++ * 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 2 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, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++/**
++ * SECTION:pk-package-item
++ * @short_description: A cached Package structure
++ *
++ * These provide a way to query and store a single package.
++ */
++
++#include "config.h"
++
++#include <stdlib.h>
++#include <stdio.h>
++#include <time.h>
++#include <errno.h>
++
++#include <string.h>
++#include <sys/time.h>
++#include <sys/types.h>
++#ifdef HAVE_UNISTD_H
++#include <unistd.h>
++#endif /* HAVE_UNISTD_H */
++
++#include <glib/gi18n.h>
++
++#include "pk-debug.h"
++#include "pk-common.h"
++#include "pk-package-item.h"
++
++/**
++ * pk_package_item_new:
++ **/
++PkPackageItem *
++pk_package_item_new (PkInfoEnum info, const gchar *package_id, const gchar *summary)
++{
++      PkPackageItem *item;
++
++      g_return_val_if_fail (package_id != NULL, FALSE);
++
++      pk_debug ("adding to cache item package %s, %s, %s", pk_info_enum_to_text (info), package_id, summary);
++      item = g_new0 (PkPackageItem, 1);
++      item->info = info;
++      item->package_id = g_strdup (package_id);
++      item->summary = g_strdup (summary);
++      return item;
++}
++
++/**
++ * pk_package_item_free:
++ **/
++gboolean
++pk_package_item_free (PkPackageItem *item)
++{
++      if (item == NULL) {
++              return FALSE;
++      }
++      g_free (item->package_id);
++      g_free (item->summary);
++      g_free (item);
++      return TRUE;
++}
++
++/**
++ * pk_package_item_equal:
++ *
++ * Only compares the package_id's and the info enum
++ **/
++gboolean
++pk_package_item_equal (PkPackageItem *item1, PkPackageItem *item2)
++{
++      if (item1 == NULL || item2 == NULL) {
++              return FALSE;
++      }
++      return (item1->info == item2->info &&
++              pk_strequal (item1->package_id, item2->package_id));
++}
++
++/**
++ * pk_package_item_copy:
++ *
++ * Copy a PkPackageItem
++ **/
++PkPackageItem *
++pk_package_item_copy (PkPackageItem *item)
++{
++      g_return_val_if_fail (item != NULL, NULL);
++      return pk_package_item_new (item->info, item->package_id, item->summary);
++}
++
++/***************************************************************************
++ ***                          MAKE CHECK TESTS                           ***
++ ***************************************************************************/
++#ifdef PK_BUILD_TESTS
++#include <libselftest.h>
++
++void
++libst_package_item (LibSelfTest *test)
++{
++      PkPackageItem *item1;
++      PkPackageItem *item2;
++      PkPackageItem *item3;
++      gboolean ret;
++
++      if (libst_start (test, "PkPackageItem", CLASS_AUTO) == FALSE) {
++              return;
++      }
++
++      /************************************************************/
++      libst_title (test, "add entry");
++      item1 = pk_package_item_new (PK_INFO_ENUM_INSTALLED, "gnome;1.23;i386;data", "GNOME!");
++      if (item1 != NULL) {
++              libst_success (test, NULL);
++      } else {
++              libst_failed (test, NULL);
++      }
++
++      /************************************************************/
++      libst_title (test, "add entry");
++      item2 = pk_package_item_new (PK_INFO_ENUM_INSTALLED, "gnome;1.23;i386;data", "GNOME foo!");
++      if (item2 != NULL) {
++              libst_success (test, NULL);
++      } else {
++              libst_failed (test, NULL);
++      }
++
++      /************************************************************/
++      libst_title (test, "copy entry");
++      item3 = pk_package_item_copy (item2);
++      if (item3 != NULL) {
++              libst_success (test, NULL);
++      } else {
++              libst_failed (test, NULL);
++      }
++
++      /************************************************************/
++      libst_title (test, "check equal");
++      ret = pk_package_item_equal (item1, item3);
++      if (ret) {
++              libst_success (test, NULL);
++      } else {
++              libst_failed (test, NULL);
++      }
++
++      pk_package_item_free (item2);
++      pk_package_item_free (item3);
++
++      /************************************************************/
++      libst_title (test, "add entry");
++      item2 = pk_package_item_new (PK_INFO_ENUM_INSTALLED, "gnome-do;1.23;i386;data", "GNOME doo!");
++      if (item2 != NULL) {
++              libst_success (test, NULL);
++      } else {
++              libst_failed (test, NULL);
++      }
++
++      /************************************************************/
++      libst_title (test, "check !equal");
++      ret = pk_package_item_equal (item1, item2);
++      if (!ret) {
++              libst_success (test, NULL);
++      } else {
++              libst_failed (test, NULL);
++      }
++
++      pk_package_item_free (item1);
++      pk_package_item_free (item2);
++
++      libst_end (test);
++}
++#endif
++
+diff --git a/libpackagekit/pk-package-item.h b/libpackagekit/pk-package-item.h
+new file mode 100644
+index 0000000..c41a6ea
+--- /dev/null
++++ b/libpackagekit/pk-package-item.h
+@@ -0,0 +1,48 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
++ *
++ * Copyright (C) 2008 Richard Hughes <richard@hughsie.com>
++ *
++ * Licensed under the GNU General Public License Version 2
++ *
++ * 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 2 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, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++#ifndef __PK_PACKAGE_ITEM_H
++#define __PK_PACKAGE_ITEM_H
++
++#include <glib-object.h>
++#include <pk-enum.h>
++
++/**
++ * PkPackageItem:
++ *
++ * A cached store for the complete Package object
++ */
++typedef struct {
++      PkInfoEnum               info;
++      gchar                   *package_id;
++      gchar                   *summary;
++} PkPackageItem;
++
++PkPackageItem *pk_package_item_new                    (PkInfoEnum              info,
++                                                       const gchar            *package_id,
++                                                       const gchar            *summary);
++gboolean       pk_package_item_free                   (PkPackageItem          *item);
++PkPackageItem *pk_package_item_copy                   (PkPackageItem          *item);
++gboolean       pk_package_item_equal                  (PkPackageItem          *item1,
++                                                       PkPackageItem          *item2);
++
++#endif /* __PK_PACKAGE_ITEM_H */
++
+diff --git a/libpackagekit/pk-package-list.c b/libpackagekit/pk-package-list.c
+index b0a1a71..5d95e1b 100644
+--- a/libpackagekit/pk-package-list.c
++++ b/libpackagekit/pk-package-list.c
+@@ -45,6 +45,7 @@
+ #include "pk-debug.h"
+ #include "pk-common.h"
+ #include "pk-package-id.h"
++#include "pk-package-item.h"
+ #include "pk-package-list.h"
+ static void     pk_package_list_class_init    (PkPackageListClass *klass);
+@@ -77,16 +78,42 @@ pk_package_list_add (PkPackageList *plist, PkInfoEnum info, const gchar *package
+       g_return_val_if_fail (package_id != NULL, FALSE);
+       pk_debug ("adding to cache array package %s, %s, %s", pk_info_enum_to_text (info), package_id, summary);
+-      item = g_new0 (PkPackageItem, 1);
+-      item->info = info;
+-      item->package_id = g_strdup (package_id);
+-      item->summary = g_strdup (summary);
++      item = pk_package_item_new (info, package_id, summary);
+       g_ptr_array_add (plist->priv->array, item);
+       return TRUE;
+ }
+ /**
++ * pk_package_list_add_item:
++ *
++ * Makes a deep copy, and adds to the array
++ **/
++gboolean
++pk_package_list_add_item (PkPackageList *plist, PkPackageItem *item)
++{
++      gboolean ret;
++      PkPackageItem *item_new;
++
++      g_return_val_if_fail (PK_IS_PACKAGE_LIST (plist), FALSE);
++      g_return_val_if_fail (item != NULL, FALSE);
++
++      ret = pk_package_list_contains_item (plist, item);
++      if (ret) {
++              pk_debug ("already added item");
++              return FALSE;
++      }
++
++      pk_debug ("adding to cache array package %s, %s, %s",
++                pk_info_enum_to_text (item->info), item->package_id, item->summary);
++
++      item_new = pk_package_item_copy (item);
++      g_ptr_array_add (plist->priv->array, item_new);
++
++      return TRUE;
++}
++
++/**
+  * pk_package_list_get_string:
+  **/
+ gchar *
+@@ -152,9 +179,7 @@ pk_package_list_clear (PkPackageList *plist)
+       while (plist->priv->array->len > 0) {
+               item = g_ptr_array_index (plist->priv->array, 0);
+-              g_free (item->package_id);
+-              g_free (item->summary);
+-              g_free (item);
++              pk_package_item_free (item);
+               g_ptr_array_remove_index_fast (plist->priv->array, 0);
+       }
+       return TRUE;
+@@ -186,6 +211,31 @@ pk_package_list_contains (PkPackageList *plist, const gchar *package_id)
+ }
+ /**
++ * pk_package_list_contains_item:
++ **/
++gboolean
++pk_package_list_contains_item (PkPackageList *plist, PkPackageItem *item)
++{
++      PkPackageItem *item_temp;
++      guint i;
++      guint length;
++      gboolean ret = FALSE;
++
++      g_return_val_if_fail (PK_IS_PACKAGE_LIST (plist), FALSE);
++      g_return_val_if_fail (item != NULL, FALSE);
++
++      length = plist->priv->array->len;
++      for (i=0; i<length; i++) {
++              item_temp = g_ptr_array_index (plist->priv->array, i);
++              ret = pk_package_item_equal (item_temp, item);
++              if (ret) {
++                      break;
++              }
++      }
++      return ret;
++}
++
++/**
+  * pk_package_list_class_init:
+  * @klass: The PkPackageListClass
+  **/
+diff --git a/libpackagekit/pk-package-list.h b/libpackagekit/pk-package-list.h
+index 9178f77..9734af4 100644
+--- a/libpackagekit/pk-package-list.h
++++ b/libpackagekit/pk-package-list.h
+@@ -25,6 +25,8 @@
+ #include <glib-object.h>
+ #include <pk-enum.h>
++#include "pk-package-item.h"
++
+ G_BEGIN_DECLS
+ #define PK_TYPE_PACKAGE_LIST          (pk_package_list_get_type ())
+@@ -49,26 +51,18 @@ struct _PkPackageListClass
+       GObjectClass    parent_class;
+ };
+-/**
+- * PkPackageItem:
+- *
+- * A cached store for the complete Package object
+- */
+-typedef struct
+-{
+-      PkInfoEnum               info;
+-      gchar                   *package_id;
+-      gchar                   *summary;
+-} PkPackageItem;
+-
+ GType          pk_package_list_get_type               (void) G_GNUC_CONST;
+ PkPackageList *pk_package_list_new                    (void);
+ gboolean       pk_package_list_add                    (PkPackageList          *plist,
+                                                        PkInfoEnum              info,
+                                                        const gchar            *package_id,
+                                                        const gchar            *summary);
++gboolean       pk_package_list_add_item               (PkPackageList          *plist,
++                                                       PkPackageItem          *item);
+ gboolean       pk_package_list_contains               (PkPackageList          *plist,
+                                                        const gchar            *package_id);
++gboolean       pk_package_list_contains_item          (PkPackageList          *plist,
++                                                       PkPackageItem          *item);
+ gchar         *pk_package_list_get_string             (PkPackageList          *plist)
+                                                        G_GNUC_WARN_UNUSED_RESULT;
+ guint          pk_package_list_get_size               (PkPackageList          *plist);
+diff --git a/libpackagekit/pk-self-test.c b/libpackagekit/pk-self-test.c
+index 62e225b..bf151fb 100644
+--- a/libpackagekit/pk-self-test.c
++++ b/libpackagekit/pk-self-test.c
+@@ -29,6 +29,7 @@
+ /* prototypes */
+ void libst_package_id (LibSelfTest *test);
+ void libst_package_ids (LibSelfTest *test);
++void libst_package_item (LibSelfTest *test);
+ void libst_package_list (LibSelfTest *test);
+ void libst_enum (LibSelfTest *test);
+ void libst_common (LibSelfTest *test);
+@@ -51,6 +52,7 @@ main (int argc, char **argv)
+       libst_common (&test);
+       libst_package_id (&test);
+       libst_package_ids (&test);
++      libst_package_item (&test);
+       libst_package_list (&test);
+       libst_enum (&test);
+       libst_extra (&test);
+diff --git a/python/packagekit/daemonBackend.py b/python/packagekit/daemonBackend.py
+index 3711f01..5253b39 100644
+--- a/python/packagekit/daemonBackend.py
++++ b/python/packagekit/daemonBackend.py
+@@ -789,6 +789,21 @@ class PackageKitBaseBackend(dbus.service.Object):
+         self.Finished(EXIT_FAILED)
+     @dbus.service.method(PACKAGEKIT_DBUS_INTERFACE,
++                         in_signature='ss', out_signature='')
++    def SetProxy(self, proxy_http, proxy_ftp):
++        '''
++        Set the proxy
++        '''
++        pklog.info("SetProxy(%s, %s)" % (proxy_http, proxy_ftp))
++        self.doSetProxy(proxy_http, proxy_ftp)
++
++    def doSetProxy(self, proxy_http, proxy_ftp):
++        '''
++        Should be replaced in the corresponding backend sub class
++        '''
++        # do not use Finished() in this method
++
++    @dbus.service.method(PACKAGEKIT_DBUS_INTERFACE,
+                          in_signature='s', out_signature='')
+     def InstallPublicKey(self, keyurl):
+         '''
+diff --git a/src/pk-backend-dbus.c b/src/pk-backend-dbus.c
+index b06e584..4c6837a 100644
+--- a/src/pk-backend-dbus.c
++++ b/src/pk-backend-dbus.c
+@@ -123,16 +123,6 @@ pk_backend_dbus_sub_percentage_changed_cb (DBusGProxy *proxy, guint sub_percenta
+ }
+ /**
+- * pk_backend_dbus_no_percentage_updates_cb:
+- **/
+-static void
+-pk_backend_dbus_no_percentage_updates_cb (DBusGProxy *proxy, PkBackendDbus *backend_dbus)
+-{
+-      pk_debug ("got signal");
+-      pk_backend_no_percentage_updates (backend_dbus->priv->backend);
+-}
+-
+-/**
+  * pk_backend_dbus_package_cb:
+  **/
+ static void
+@@ -325,8 +315,6 @@ pk_backend_dbus_remove_callbacks (PkBackendDbus *backend_dbus)
+                                       G_CALLBACK (pk_backend_dbus_percentage_changed_cb), backend_dbus);
+       dbus_g_proxy_disconnect_signal (proxy, "SubPercentageChanged",
+                                       G_CALLBACK (pk_backend_dbus_sub_percentage_changed_cb), backend_dbus);
+-      dbus_g_proxy_disconnect_signal (proxy, "NoPercentageChanged",
+-                                      G_CALLBACK (pk_backend_dbus_no_percentage_updates_cb), backend_dbus);
+       dbus_g_proxy_disconnect_signal (proxy, "Package",
+                                       G_CALLBACK (pk_backend_dbus_package_cb), backend_dbus);
+       dbus_g_proxy_disconnect_signal (proxy, "Details",
+@@ -353,6 +341,31 @@ pk_backend_dbus_remove_callbacks (PkBackendDbus *backend_dbus)
+ }
+ /**
++ * pk_backend_dbus_set_proxy:
++ **/
++static gboolean
++pk_backend_dbus_set_proxy (PkBackendDbus *backend_dbus, const gchar *proxy_http, const gchar *proxy_ftp)
++{
++      gboolean ret;
++      GError *error = NULL;
++
++      g_return_val_if_fail (PK_IS_BACKEND_DBUS (backend_dbus), FALSE);
++      g_return_val_if_fail (backend_dbus->priv->proxy != NULL, FALSE);
++
++      /* new sync method call */
++      pk_backend_dbus_time_reset (backend_dbus);
++      ret = dbus_g_proxy_call (backend_dbus->priv->proxy, "SetProxy", &error,
++                               G_TYPE_STRING, proxy_http,
++                               G_TYPE_STRING, proxy_ftp,
++                               G_TYPE_INVALID, G_TYPE_INVALID);
++      if (error != NULL) {
++              pk_warning ("%s", error->message);
++              g_error_free (error);
++      }
++      return ret;
++}
++
++/**
+  * pk_backend_dbus_set_name:
+  **/
+ gboolean
+@@ -385,7 +398,6 @@ pk_backend_dbus_set_name (PkBackendDbus *backend_dbus, const gchar *service)
+                                G_TYPE_UINT, G_TYPE_INVALID);
+       dbus_g_proxy_add_signal (proxy, "SubPercentageChanged",
+                                G_TYPE_UINT, G_TYPE_INVALID);
+-      dbus_g_proxy_add_signal (proxy, "NoPercentageChanged", G_TYPE_INVALID);
+       dbus_g_proxy_add_signal (proxy, "Package",
+                                G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
+       dbus_g_proxy_add_signal (proxy, "Details",
+@@ -424,8 +436,6 @@ pk_backend_dbus_set_name (PkBackendDbus *backend_dbus, const gchar *service)
+                                    G_CALLBACK (pk_backend_dbus_percentage_changed_cb), backend_dbus, NULL);
+       dbus_g_proxy_connect_signal (proxy, "SubPercentageChanged",
+                                    G_CALLBACK (pk_backend_dbus_sub_percentage_changed_cb), backend_dbus, NULL);
+-      dbus_g_proxy_connect_signal (proxy, "NoPercentageChanged",
+-                                   G_CALLBACK (pk_backend_dbus_no_percentage_updates_cb), backend_dbus, NULL);
+       dbus_g_proxy_connect_signal (proxy, "Package",
+                                    G_CALLBACK (pk_backend_dbus_package_cb), backend_dbus, NULL);
+       dbus_g_proxy_connect_signal (proxy, "Details",
+@@ -465,6 +475,18 @@ pk_backend_dbus_set_name (PkBackendDbus *backend_dbus, const gchar *service)
+               pk_backend_finished (backend_dbus->priv->backend);
+               g_error_free (error);
+       }
++
++      /* set the proxy */
++      if (ret) {
++              gchar *proxy_http;
++              gchar *proxy_ftp;
++              proxy_http = pk_backend_get_proxy_http (backend_dbus->priv->backend);
++              proxy_ftp = pk_backend_get_proxy_http (backend_dbus->priv->backend);
++              pk_backend_dbus_set_proxy (backend_dbus, proxy_http, proxy_ftp);
++              g_free (proxy_http);
++              g_free (proxy_ftp);
++      }
++
+       if (ret) {
+               pk_backend_dbus_time_check (backend_dbus);
+       }
+diff --git a/src/pk-backend-internal.h b/src/pk-backend-internal.h
+index 2213fed..2bffaff 100644
+--- a/src/pk-backend-internal.h
++++ b/src/pk-backend-internal.h
+@@ -59,6 +59,9 @@ gboolean      pk_backend_reset                       (PkBackend      *backend);
+ gboolean       pk_backend_set_name                    (PkBackend      *backend,
+                                                        const gchar    *name)
+                                                        G_GNUC_WARN_UNUSED_RESULT;
++gboolean       pk_backend_set_proxy                   (PkBackend      *backend,
++                                                       const gchar    *proxy_http,
++                                                       const gchar    *proxy_ftp);
+ gchar         *pk_backend_get_name                    (PkBackend      *backend)
+                                                        G_GNUC_WARN_UNUSED_RESULT;
+ gboolean       pk_backend_get_backend_detail          (PkBackend      *backend,
+diff --git a/src/pk-backend-spawn.c b/src/pk-backend-spawn.c
+index f9e8b68..f9c9f12 100644
+--- a/src/pk-backend-spawn.c
++++ b/src/pk-backend-spawn.c
+@@ -313,7 +313,7 @@ pk_backend_spawn_parse_stdout (PkBackendSpawn *backend_spawn, const gchar *line)
+                       ret = FALSE;
+                       goto out;
+               }
+-              pk_backend_no_percentage_updates (backend_spawn->priv->backend);
++              pk_backend_set_percentage (backend_spawn->priv->backend, PK_BACKEND_PERCENTAGE_INVALID);
+       } else if (pk_strequal (command, "repo-signature-required")) {
+               if (size != 9+99) {
+@@ -440,6 +440,44 @@ pk_backend_spawn_helper_new (PkBackendSpawn *backend_spawn)
+ }
+ /**
++ * pk_backend_spawn_get_envp:
++ *
++ * Return all the environment variables the script will need
++ **/
++static gchar **
++pk_backend_spawn_get_envp (PkBackendSpawn *backend_spawn)
++{
++      gchar **envp;
++      gchar *value;
++      gchar *line;
++      GPtrArray *array;
++
++      array = g_ptr_array_new ();
++
++      /* http_proxy */
++      value = pk_backend_get_proxy_http (backend_spawn->priv->backend);
++      if (!pk_strzero (value)) {
++              line = g_strdup_printf ("%s=%s", "http_proxy", value);
++              pk_debug ("setting evp '%s'", line);
++              g_ptr_array_add (array, line);
++      }
++      g_free (value);
++
++      /* ftp_proxy */
++      value = pk_backend_get_proxy_ftp (backend_spawn->priv->backend);
++      if (!pk_strzero (value)) {
++              line = g_strdup_printf ("%s=%s", "ftp_proxy", value);
++              pk_debug ("setting evp '%s'", line);
++              g_ptr_array_add (array, line);
++      }
++      g_free (value);
++
++      envp = pk_ptr_array_to_argv (array);
++      g_ptr_array_free (array, TRUE);
++      return envp;
++}
++
++/**
+  * pk_backend_spawn_helper_va_list:
+  **/
+ static gboolean
+@@ -448,6 +486,7 @@ pk_backend_spawn_helper_va_list (PkBackendSpawn *backend_spawn, const gchar *exe
+       gboolean ret;
+       gchar *filename;
+       gchar **argv;
++      gchar **envp;
+       g_return_val_if_fail (PK_IS_BACKEND_SPAWN (backend_spawn), FALSE);
+@@ -476,7 +515,8 @@ pk_backend_spawn_helper_va_list (PkBackendSpawn *backend_spawn, const gchar *exe
+       argv[0] = g_strdup (filename);
+       pk_backend_spawn_helper_new (backend_spawn);
+-      ret = pk_spawn_argv (backend_spawn->priv->spawn, argv);
++      envp = pk_backend_spawn_get_envp (backend_spawn);
++      ret = pk_spawn_argv (backend_spawn->priv->spawn, argv, envp);
+       if (!ret) {
+               pk_backend_spawn_helper_delete (backend_spawn);
+               pk_backend_error_code (backend_spawn->priv->backend, PK_ERROR_ENUM_INTERNAL_ERROR,
+diff --git a/src/pk-backend.c b/src/pk-backend.c
+index 225c488..37ed024 100644
+--- a/src/pk-backend.c
++++ b/src/pk-backend.c
+@@ -33,6 +33,7 @@
+ #include <glib/gprintf.h>
+ #include <pk-network.h>
++#include "pk-package-item.h"
+ #include "pk-debug.h"
+ #include "pk-common.h"
+ #include "pk-marshal.h"
+@@ -44,13 +45,6 @@
+ #define PK_BACKEND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PK_TYPE_BACKEND, PkBackendPrivate))
+ /**
+- * PK_BACKEND_PERCENTAGE_INVALID:
+- *
+- * The unknown percentage value
+- */
+-#define PK_BACKEND_PERCENTAGE_INVALID         101
+-
+-/**
+  * PK_BACKEND_PERCENTAGE_DEFAULT:
+  *
+  * The default percentage value, should never be emitted, but should be
+@@ -84,12 +78,15 @@ struct _PkBackendPrivate
+       GHashTable              *eulas;
+       gchar                   *name;
+       gchar                   *c_tid;
++      gchar                   *proxy_http;
++      gchar                   *proxy_ftp;
+       gboolean                 locked;
+       gboolean                 set_error;
+       gboolean                 set_signature;
+       gboolean                 set_eula;
+       gboolean                 has_sent_package;
+       PkNetwork               *network;
++      PkPackageItem           *last_package;
+       PkRoleEnum               role; /* this never changes for the lifetime of a transaction */
+       PkStatusEnum             status; /* this changes */
+       PkExitEnum               exit;
+@@ -592,6 +589,44 @@ out:
+ }
+ /**
++ * pk_backend_set_proxy:
++ **/
++gboolean
++pk_backend_set_proxy (PkBackend       *backend, const gchar *proxy_http, const gchar *proxy_ftp)
++{
++      g_return_val_if_fail (PK_IS_BACKEND (backend), FALSE);
++      g_free (backend->priv->proxy_http);
++      g_free (backend->priv->proxy_ftp);
++      backend->priv->proxy_http = g_strdup (proxy_http);
++      backend->priv->proxy_ftp = g_strdup (proxy_ftp);
++      return TRUE;
++}
++
++/**
++ * pk_backend_get_proxy_http:
++ *
++ * Return value: proxy string in the form username:password@server:port
++ **/
++gchar *
++pk_backend_get_proxy_http (PkBackend *backend)
++{
++      g_return_val_if_fail (PK_IS_BACKEND (backend), NULL);
++      return g_strdup (backend->priv->proxy_http);
++}
++
++/**
++ * pk_backend_get_proxy_ftp:
++ *
++ * Return value: proxy string in the form username:password@server:port
++ **/
++gchar *
++pk_backend_get_proxy_ftp (PkBackend *backend)
++{
++      g_return_val_if_fail (PK_IS_BACKEND (backend), NULL);
++      return g_strdup (backend->priv->proxy_ftp);
++}
++
++/**
+  * pk_backend_lock:
+  *
+  * Responsible for initialising the external backend object.
+@@ -803,35 +838,6 @@ pk_backend_set_sub_percentage (PkBackend *backend, guint percentage)
+ }
+ /**
+- * pk_backend_no_percentage_updates:
+- **/
+-gboolean
+-pk_backend_no_percentage_updates (PkBackend *backend)
+-{
+-      g_return_val_if_fail (PK_IS_BACKEND (backend), FALSE);
+-      g_return_val_if_fail (backend->priv->locked != FALSE, FALSE);
+-
+-      /* have we already set an error? */
+-      if (backend->priv->set_error) {
+-              pk_warning ("already set error, cannot process");
+-              return FALSE;
+-      }
+-
+-      /* set the same twice? */
+-      if (backend->priv->last_percentage == PK_BACKEND_PERCENTAGE_INVALID) {
+-              pk_debug ("duplicate set of %i", PK_BACKEND_PERCENTAGE_INVALID);
+-              return FALSE;
+-      }
+-
+-      /* invalidate previous percentage */
+-      backend->priv->last_percentage = PK_BACKEND_PERCENTAGE_INVALID;
+-
+-      /* emit the progress changed signal */
+-      pk_backend_emit_progress_changed (backend);
+-      return TRUE;
+-}
+-
+-/**
+  * pk_backend_set_status:
+  **/
+ gboolean
+@@ -901,11 +907,26 @@ gboolean
+ pk_backend_package (PkBackend *backend, PkInfoEnum info, const gchar *package_id, const gchar *summary)
+ {
+       gchar *summary_safe;
++      PkPackageItem *item;
++      gboolean ret;
+       g_return_val_if_fail (PK_IS_BACKEND (backend), FALSE);
+       g_return_val_if_fail (package_id != NULL, FALSE);
+       g_return_val_if_fail (backend->priv->locked != FALSE, FALSE);
++      /* check against the old one */
++      item = pk_package_item_new (info, package_id, summary);
++      ret = pk_package_item_equal (item, backend->priv->last_package);
++      if (ret) {
++              pk_package_item_free (item);
++              pk_debug ("skipping duplicate %s", package_id);
++              return FALSE;
++      }
++      /* update the 'last' package */
++      pk_package_item_free (backend->priv->last_package);
++      backend->priv->last_package = pk_package_item_copy (item);
++      pk_package_item_free (item);
++
+       /* have we already set an error? */
+       if (backend->priv->set_error) {
+               pk_warning ("already set error, cannot process");
+@@ -1689,6 +1710,8 @@ pk_backend_finalize (GObject *object)
+       pk_debug ("backend finalise");
+       pk_backend_reset (backend);
++      g_free (backend->priv->proxy_http);
++      g_free (backend->priv->proxy_ftp);
+       g_free (backend->priv->name);
+       g_free (backend->priv->c_tid);
+       g_object_unref (backend->priv->time);
+@@ -1818,6 +1841,7 @@ pk_backend_reset (PkBackend *backend)
+       /* TODO: need to wait for Finished() if running */
++      pk_package_item_free (backend->priv->last_package);
+       backend->priv->set_error = FALSE;
+       backend->priv->set_signature = FALSE;
+       backend->priv->set_eula = FALSE;
+@@ -1825,6 +1849,7 @@ pk_backend_reset (PkBackend *backend)
+       backend->priv->finished = FALSE;
+       backend->priv->has_sent_package = FALSE;
+       backend->priv->thread = NULL;
++      backend->priv->last_package = NULL;
+       backend->priv->status = PK_STATUS_ENUM_UNKNOWN;
+       backend->priv->exit = PK_EXIT_ENUM_UNKNOWN;
+       backend->priv->role = PK_ROLE_ENUM_UNKNOWN;
+@@ -1855,8 +1880,11 @@ pk_backend_init (PkBackend *backend)
+       backend->priv->handle = NULL;
+       backend->priv->name = NULL;
+       backend->priv->c_tid = NULL;
++      backend->priv->proxy_http = NULL;
++      backend->priv->proxy_ftp = NULL;
+       backend->priv->file_changed_func = NULL;
+       backend->priv->file_changed_data = NULL;
++      backend->priv->last_package = NULL;
+       backend->priv->locked = FALSE;
+       backend->priv->signal_finished = 0;
+       backend->priv->signal_error_timeout = 0;
+diff --git a/src/pk-backend.h b/src/pk-backend.h
+index 95b7fa8..fb17e3c 100644
+--- a/src/pk-backend.h
++++ b/src/pk-backend.h
+@@ -30,6 +30,13 @@
+ G_BEGIN_DECLS
++/**
++ * PK_BACKEND_PERCENTAGE_INVALID:
++ *
++ * The unknown percentage value
++ */
++#define PK_BACKEND_PERCENTAGE_INVALID         101
++
+ typedef struct _PkBackend PkBackend;
+ /* set the state */
+@@ -51,7 +58,6 @@ gboolean      pk_backend_set_sub_percentage          (PkBackend      *backend,
+                                                        guint           percentage);
+ gboolean       pk_backend_set_exit_code               (PkBackend      *backend,
+                                                        PkExitEnum      exit);
+-gboolean       pk_backend_no_percentage_updates       (PkBackend      *backend);
+ gboolean       pk_backend_set_transaction_data        (PkBackend      *backend,
+                                                        const gchar    *data);
+@@ -66,6 +72,8 @@ gboolean      pk_backend_get_progress                (PkBackend      *backend,
+                                                        guint          *elapsed,
+                                                        guint          *remaining);
+ guint          pk_backend_get_runtime                 (PkBackend      *backend);
++gchar         *pk_backend_get_proxy_ftp               (PkBackend      *backend);
++gchar         *pk_backend_get_proxy_http              (PkBackend      *backend);
+ /* signal helpers */
+ gboolean       pk_backend_finished                    (PkBackend      *backend);
+diff --git a/src/pk-engine.c b/src/pk-engine.c
+index db81d36..028a0d0 100644
+--- a/src/pk-engine.c
++++ b/src/pk-engine.c
+@@ -101,6 +101,7 @@ struct PkEnginePrivate
+       PkNetwork               *network;
+       PkSecurity              *security;
+       PkNotify                *notify;
++      PkConf                  *conf;
+       PkFileMonitor           *file_monitor;
+       PkRoleEnum               actions;
+       PkGroupEnum              groups;
+@@ -579,10 +580,15 @@ pk_engine_init (PkEngine *engine)
+       DBusGConnection *connection;
+       gboolean ret;
+       gchar *filename;
++      gchar *proxy_http;
++      gchar *proxy_ftp;
+       engine->priv = PK_ENGINE_GET_PRIVATE (engine);
+       engine->priv->restart_schedule = FALSE;
++      /* use the config file */
++      engine->priv->conf = pk_conf_new ();
++
+       /* setup the backend backend */
+       engine->priv->backend = pk_backend_new ();
+       g_signal_connect (engine->priv->backend, "finished",
+@@ -639,6 +645,13 @@ pk_engine_init (PkEngine *engine)
+                         G_CALLBACK (pk_engine_file_monitor_changed_cb), engine);
+       g_free (filename);
++      /* set the proxy */
++      proxy_http = pk_conf_get_string (engine->priv->conf, "ProxyHTTP");
++      proxy_ftp = pk_conf_get_string (engine->priv->conf, "ProxyFTP");
++      pk_backend_set_proxy (engine->priv->backend, proxy_http, proxy_ftp);
++      g_free (proxy_http);
++      g_free (proxy_ftp);
++
+       engine->priv->transaction_list = pk_transaction_list_new ();
+       g_signal_connect (engine->priv->transaction_list, "changed",
+                         G_CALLBACK (pk_engine_transaction_list_changed_cb), engine);
+@@ -696,6 +709,7 @@ pk_engine_finalize (GObject *object)
+       g_object_unref (engine->priv->notify);
+       g_object_unref (engine->priv->backend);
+       g_object_unref (engine->priv->cache);
++      g_object_unref (engine->priv->conf);
+       G_OBJECT_CLASS (pk_engine_parent_class)->finalize (object);
+ }
+diff --git a/src/pk-network-unix.c b/src/pk-network-unix.c
+index 11c23a2..74b266c 100644
+--- a/src/pk-network-unix.c
++++ b/src/pk-network-unix.c
+@@ -138,6 +138,11 @@ pk_network_unix_get_network_state (PkNetworkUnix *network_unix)
+                       continue;
+               }
++              /* is loopback? */
++              if (pk_strequal (sections[0], "lo")) {
++                      continue;
++              }
++
+               /* is correct parameters? */
+               number_sections = g_strv_length (sections);
+               if (number_sections != 11) {
+@@ -145,9 +150,8 @@ pk_network_unix_get_network_state (PkNetworkUnix *network_unix)
+                       continue;
+               }
+-              /* is MTU and gateway nonzero? */
+-              if (!pk_strequal (sections[8], "0") &&
+-                  !pk_strequal (sections[2], "00000000")) {
++              /* is gateway nonzero? */
++              if (!pk_strequal (sections[2], "00000000")) {
+                       pk_debug ("interface %s is valid", sections[0]);
+                       online = TRUE;
+               }
+diff --git a/src/pk-network.c b/src/pk-network.c
+index 9656958..0ad839e 100644
+--- a/src/pk-network.c
++++ b/src/pk-network.c
+@@ -39,6 +39,7 @@
+ #ifdef HAVE_UNISTD_H
+ #include <unistd.h>
+ #endif /* HAVE_UNISTD_H */
++#include <libgbus.h>
+ #include <glib/gi18n.h>
+@@ -67,6 +68,7 @@ struct _PkNetworkPrivate
+       PkNetworkNm             *net_nm;
+       PkNetworkUnix           *net_unix;
+       PkConf                  *conf;
++      LibGBus                 *nm_bus;
+ };
+ enum {
+@@ -154,6 +156,7 @@ pk_network_class_init (PkNetworkClass *klass)
+ static void
+ pk_network_init (PkNetwork *network)
+ {
++      gboolean nm_alive;
+       network->priv = PK_NETWORK_GET_PRIVATE (network);
+       network->priv->conf = pk_conf_new ();
+       network->priv->net_nm = pk_network_nm_new ();
+@@ -167,6 +170,17 @@ pk_network_init (PkNetwork *network)
+       network->priv->use_nm = pk_conf_get_bool (network->priv->conf, "UseNetworkManager");
+       network->priv->use_unix = pk_conf_get_bool (network->priv->conf, "UseNetworkHeuristic");
++      /* check if NM is on the bus */
++      network->priv->nm_bus = libgbus_new ();
++      libgbus_assign (network->priv->nm_bus, LIBGBUS_SYSTEM, "org.freedesktop.NetworkManager");
++      nm_alive = libgbus_is_connected (network->priv->nm_bus);
++
++      /* NetworkManager isn't up, so we can't use it */
++      if (network->priv->use_nm && !nm_alive) {
++              pk_warning ("UseNetworkManager true, but org.freedesktop.NetworkManager not up");
++              network->priv->use_nm = FALSE;
++      }
++
+ #if !PK_BUILD_NETWORKMANAGER
+       /* check we can actually use the default */
+       if (network->priv->use_nm) {
+@@ -190,6 +204,7 @@ pk_network_finalize (GObject *object)
+       g_return_if_fail (network->priv != NULL);
+       g_object_unref (network->priv->conf);
++      g_object_unref (network->priv->nm_bus);
+       g_object_unref (network->priv->net_nm);
+       g_object_unref (network->priv->net_unix);
+       G_OBJECT_CLASS (pk_network_parent_class)->finalize (object);
+diff --git a/src/pk-spawn.c b/src/pk-spawn.c
+index 9b415b1..c4622f9 100644
+--- a/src/pk-spawn.c
++++ b/src/pk-spawn.c
+@@ -273,7 +273,7 @@ pk_spawn_kill (PkSpawn *spawn)
+  *
+  **/
+ gboolean
+-pk_spawn_argv (PkSpawn *spawn, gchar **argv)
++pk_spawn_argv (PkSpawn *spawn, gchar **argv, gchar **envp)
+ {
+       gboolean ret;
+@@ -284,7 +284,7 @@ pk_spawn_argv (PkSpawn *spawn, gchar **argv)
+       spawn->priv->finished = FALSE;
+       /* create spawned object for tracking */
+-      ret = g_spawn_async_with_pipes (NULL, argv, NULL,
++      ret = g_spawn_async_with_pipes (NULL, argv, envp,
+                                G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH,
+                                NULL, NULL, &spawn->priv->child_pid,
+                                NULL, /* stdin */
+@@ -484,6 +484,7 @@ libst_spawn (LibSelfTest *test)
+       gboolean ret;
+       gchar *path;
+       gchar **argv;
++      gchar **envp;
+       if (libst_start (test, "PkSpawn", CLASS_AUTO) == FALSE) {
+               return;
+@@ -496,7 +497,7 @@ libst_spawn (LibSelfTest *test)
+       libst_title (test, "make sure return error for missing file");
+       mexit = BAD_EXIT;
+       argv = g_strsplit ("pk-spawn-test-xxx.sh", " ", 0);
+-      ret = pk_spawn_argv (spawn, argv);
++      ret = pk_spawn_argv (spawn, argv, NULL);
+       g_strfreev (argv);
+       if (ret == FALSE) {
+               libst_success (test, "failed to run invalid file");
+@@ -517,7 +518,7 @@ libst_spawn (LibSelfTest *test)
+       mexit = -1;
+       path = pk_test_get_data ("pk-spawn-test.sh");
+       argv = g_strsplit (path, " ", 0);
+-      ret = pk_spawn_argv (spawn, argv);
++      ret = pk_spawn_argv (spawn, argv, NULL);
+       g_free (path);
+       g_strfreev (argv);
+       if (ret) {
+@@ -558,11 +559,34 @@ libst_spawn (LibSelfTest *test)
+       new_spawn_object (test, &spawn);
+       /************************************************************/
++      libst_title (test, "make sure we set the proxy");
++      mexit = -1;
++      path = pk_test_get_data ("pk-spawn-proxy.sh");
++      argv = g_strsplit (path, " ", 0);
++      envp = g_strsplit ("http_proxy=username:password@server:port "
++                         "ftp_proxy=username:password@server:port", " ", 0);
++      ret = pk_spawn_argv (spawn, argv, envp);
++      g_free (path);
++      g_strfreev (argv);
++      if (ret) {
++              libst_success (test, "ran correct file");
++      } else {
++              libst_failed (test, "did not run helper");
++      }
++
++      /* wait for finished */
++      libst_loopwait (test, 10000);
++      libst_loopcheck (test);
++
++      /* get new object */
++      new_spawn_object (test, &spawn);
++
++      /************************************************************/
+       libst_title (test, "make sure run correct helper, and kill it");
+       mexit = BAD_EXIT;
+       path = pk_test_get_data ("pk-spawn-test.sh");
+       argv = g_strsplit (path, " ", 0);
+-      ret = pk_spawn_argv (spawn, argv);
++      ret = pk_spawn_argv (spawn, argv, NULL);
+       g_free (path);
+       g_strfreev (argv);
+       if (ret) {
+@@ -592,7 +616,7 @@ libst_spawn (LibSelfTest *test)
+       mexit = BAD_EXIT;
+       path = pk_test_get_data ("pk-spawn-test-sigquit.sh");
+       argv = g_strsplit (path, " ", 0);
+-      ret = pk_spawn_argv (spawn, argv);
++      ret = pk_spawn_argv (spawn, argv, NULL);
+       g_free (path);
+       g_strfreev (argv);
+       if (ret) {
+@@ -618,7 +642,7 @@ libst_spawn (LibSelfTest *test)
+       libst_title (test, "run lots of data for profiling");
+       path = pk_test_get_data ("pk-spawn-test-profiling.sh");
+       argv = g_strsplit (path, " ", 0);
+-      ret = pk_spawn_argv (spawn, argv);
++      ret = pk_spawn_argv (spawn, argv, NULL);
+       g_free (path);
+       g_strfreev (argv);
+       if (ret) {
+diff --git a/src/pk-spawn.h b/src/pk-spawn.h
+index 1b20fef..0e58859 100644
+--- a/src/pk-spawn.h
++++ b/src/pk-spawn.h
+@@ -52,7 +52,8 @@ GType                 pk_spawn_get_type                      (void) G_GNUC_CONST;
+ PkSpawn               *pk_spawn_new                           (void);
+ gboolean       pk_spawn_argv                          (PkSpawn        *spawn,
+-                                                       gchar          **argv)
++                                                       gchar          **argv,
++                                                       gchar          **envp)
+                                                        G_GNUC_WARN_UNUSED_RESULT;
+ gboolean       pk_spawn_kill                          (PkSpawn        *spawn);
diff --git a/packages/packagekit/files/02_9ced8313fb12f0f89ad6ced7c0fdc7241ff00d77.patch b/packages/packagekit/files/02_9ced8313fb12f0f89ad6ced7c0fdc7241ff00d77.patch
new file mode 100644 (file)
index 0000000..fb617c5
--- /dev/null
@@ -0,0 +1,13544 @@
+:000000 100644 0000000... bd0cc2e... A RELEASE
+:100644 100644 fcc8347... 20279b3... M backends/Makefile.am
+:000000 100644 0000000... c851833... A backends/apt.deprecated/.gitignore
+:000000 100644 0000000... 07b4131... A backends/apt.deprecated/Makefile.am
+:000000 100644 0000000... 0d20b64... A backends/apt.deprecated/helpers/.gitignore
+:000000 100644 0000000... 0299df2... A backends/apt.deprecated/helpers/Makefile.am
+:000000 100644 0000000... e5f78ca... A backends/apt.deprecated/helpers/aptBackend.py
+:000000 100755 0000000... 94dca4a... A backends/apt.deprecated/helpers/get-depends.py
+:000000 100755 0000000... a813640... A backends/apt.deprecated/helpers/get-details.py
+:000000 100755 0000000... 5529f72... A backends/apt.deprecated/helpers/get-repo-list.py
+:000000 100755 0000000... e581010... A backends/apt.deprecated/helpers/get-requires.py
+:000000 100755 0000000... 5524d9a... A backends/apt.deprecated/helpers/get-update-detail.py
+:000000 100755 0000000... 4f45fbf... A backends/apt.deprecated/helpers/get-updates.py
+:000000 100755 0000000... dfa024c... A backends/apt.deprecated/helpers/install-files.py
+:000000 120000 0000000... 8d22531... A backends/apt.deprecated/helpers/packagekit
+:000000 100755 0000000... 881479d... A backends/apt.deprecated/helpers/refresh-cache.py
+:000000 100755 0000000... 3cc36ae... A backends/apt.deprecated/helpers/repo-enable.py
+:000000 100755 0000000... aac34df... A backends/apt.deprecated/helpers/resolve.py
+:000000 100755 0000000... d02f1b0... A backends/apt.deprecated/helpers/search-details.py
+:000000 100755 0000000... ec60319... A backends/apt.deprecated/helpers/search-file.py
+:000000 100755 0000000... f63ee80... A backends/apt.deprecated/helpers/search-group.py
+:000000 100755 0000000... 9f73c89... A backends/apt.deprecated/helpers/search-name.py
+:000000 100644 0000000... 885275d... A backends/apt.deprecated/pk-apt-build-db.cpp
+:000000 100644 0000000... bb786a9... A backends/apt.deprecated/pk-apt-build-db.h
+:000000 100644 0000000... 5e5b4e5... A backends/apt.deprecated/pk-apt-search-plain.c
+:000000 100644 0000000... 98bdc7f... A backends/apt.deprecated/pk-apt-search-sqlite.cpp
+:000000 100644 0000000... e36e89f... A backends/apt.deprecated/pk-apt-search.h
+:000000 100644 0000000... f59cd88... A backends/apt.deprecated/pk-backend-apt.c
+:000000 100644 0000000... 1bf9a50... A backends/apt.deprecated/pk-sqlite-pkg-cache.cpp
+:000000 100644 0000000... 68fad42... A backends/apt.deprecated/pk-sqlite-pkg-cache.h
+:000000 100644 0000000... 2b99c5d... A backends/apt/HACKING
+:100644 100644 07b4131... e315ba9... M backends/apt/Makefile.am
+:000000 100644 0000000... 0a3da6e... A backends/apt/README
+:000000 100644 0000000... bee2f3d... A backends/apt/TODO
+:000000 100755 0000000... 22eb714... A backends/apt/aptDBUSBackend.py
+:100644 000000 0d20b64... 0000000... D backends/apt/helpers/.gitignore
+:100644 000000 0299df2... 0000000... D backends/apt/helpers/Makefile.am
+:100644 000000 e5f78ca... 0000000... D backends/apt/helpers/aptBackend.py
+:100755 000000 94dca4a... 0000000... D backends/apt/helpers/get-depends.py
+:100755 000000 a813640... 0000000... D backends/apt/helpers/get-details.py
+:100755 000000 5529f72... 0000000... D backends/apt/helpers/get-repo-list.py
+:100755 000000 e581010... 0000000... D backends/apt/helpers/get-requires.py
+:100755 000000 5524d9a... 0000000... D backends/apt/helpers/get-update-detail.py
+:100755 000000 4f45fbf... 0000000... D backends/apt/helpers/get-updates.py
+:100755 000000 dfa024c... 0000000... D backends/apt/helpers/install-files.py
+:100755 000000 881479d... 0000000... D backends/apt/helpers/refresh-cache.py
+:100755 000000 3cc36ae... 0000000... D backends/apt/helpers/repo-enable.py
+:100755 000000 aac34df... 0000000... D backends/apt/helpers/resolve.py
+:100755 000000 d02f1b0... 0000000... D backends/apt/helpers/search-details.py
+:100755 000000 ec60319... 0000000... D backends/apt/helpers/search-file.py
+:100755 000000 f63ee80... 0000000... D backends/apt/helpers/search-group.py
+:100755 000000 9f73c89... 0000000... D backends/apt/helpers/search-name.py
+:000000 120000 0000000... 0b64032... A backends/apt/packagekit
+:100644 000000 885275d... 0000000... D backends/apt/pk-apt-build-db.cpp
+:100644 000000 bb786a9... 0000000... D backends/apt/pk-apt-build-db.h
+:100644 000000 5e5b4e5... 0000000... D backends/apt/pk-apt-search-plain.c
+:100644 000000 98bdc7f... 0000000... D backends/apt/pk-apt-search-sqlite.cpp
+:100644 000000 e36e89f... 0000000... D backends/apt/pk-apt-search.h
+:100644 100644 f59cd88... 70836b2... M backends/apt/pk-backend-apt.c
+:100644 000000 1bf9a50... 0000000... D backends/apt/pk-sqlite-pkg-cache.cpp
+:100644 000000 68fad42... 0000000... D backends/apt/pk-sqlite-pkg-cache.h
+:000000 100644 0000000... 1b5d30f... A backends/apt/profiler.py
+:000000 100755 0000000... a1d5ffb... A backends/apt/test.py
+:100644 000000 c851833... 0000000... D backends/apt2/.gitignore
+:100644 000000 2b99c5d... 0000000... D backends/apt2/HACKING
+:100644 000000 91c0c46... 0000000... D backends/apt2/Makefile.am
+:100644 000000 0a3da6e... 0000000... D backends/apt2/README
+:100644 000000 bee2f3d... 0000000... D backends/apt2/TODO
+:100755 000000 b7fc500... 0000000... D backends/apt2/aptDBUSBackend.py
+:120000 000000 0b64032... 0000000... D backends/apt2/packagekit
+:100644 000000 4f78ec4... 0000000... D backends/apt2/pk-backend-apt2.c
+:100644 000000 1b5d30f... 0000000... D backends/apt2/profiler.py
+:100755 000000 a1d5ffb... 0000000... D backends/apt2/test.py
+:100644 100644 2df445e... 5714e9f... M backends/dummy/pk-backend-dummy.c
+:100644 100644 7649bab... 2d70108... M backends/opkg/pk-backend-opkg.c
+:100644 100644 fdc99d3... 2691414... M backends/poldek/pk-backend-poldek.c
+:000000 100644 0000000... 996fb0d... A backends/urpmi/.gitignore
+:000000 100644 0000000... 56743a1... A backends/urpmi/Makefile.am
+:000000 100644 0000000... 2f78cf5... A backends/urpmi/helpers/.gitignore
+:000000 100644 0000000... 88f144e... A backends/urpmi/helpers/Makefile.am
+:000000 100755 0000000... bf936c5... A backends/urpmi/helpers/get-depends.pl
+:000000 100755 0000000... 3207e9b... A backends/urpmi/helpers/get-details.pl
+:000000 100755 0000000... 74ae157... A backends/urpmi/helpers/get-files.pl
+:000000 100755 0000000... 9e3e525... A backends/urpmi/helpers/get-packages.pl
+:000000 100755 0000000... 0012b2a... A backends/urpmi/helpers/get-requires.pl
+:000000 100755 0000000... 69ea452... A backends/urpmi/helpers/get-update-detail.pl
+:000000 100755 0000000... 02d574c... A backends/urpmi/helpers/get-updates.pl
+:000000 100755 0000000... c9cf6c8... A backends/urpmi/helpers/install-packages.pl
+:000000 100644 0000000... 6ed63b5... A backends/urpmi/helpers/perl_packagekit/Makefile.am
+:000000 100644 0000000... 8dbb4b0... A backends/urpmi/helpers/perl_packagekit/enums.pm
+:000000 100644 0000000... 7411ca9... A backends/urpmi/helpers/perl_packagekit/prints.pm
+:000000 100755 0000000... 555a8b8... A backends/urpmi/helpers/refresh-cache.pl
+:000000 100755 0000000... 3be38ea... A backends/urpmi/helpers/remove-packages.pl
+:000000 100755 0000000... 32e0866... A backends/urpmi/helpers/resolve.pl
+:000000 100755 0000000... 3081abe... A backends/urpmi/helpers/search-details.pl
+:000000 100755 0000000... 03d348e... A backends/urpmi/helpers/search-file.pl
+:000000 100755 0000000... e5b7b92... A backends/urpmi/helpers/search-group.pl
+:000000 100755 0000000... 383921f... A backends/urpmi/helpers/search-name.pl
+:000000 100755 0000000... 88274bc... A backends/urpmi/helpers/update-packages.pl
+:000000 100644 0000000... 3eb8280... A backends/urpmi/helpers/urpmi_backend/Makefile.am
+:000000 100644 0000000... a01b893... A backends/urpmi/helpers/urpmi_backend/actions.pm
+:000000 100644 0000000... 2c2f13a... A backends/urpmi/helpers/urpmi_backend/filters.pm
+:000000 100644 0000000... d377ab2... A backends/urpmi/helpers/urpmi_backend/groups.pm
+:000000 100644 0000000... 795edc6... A backends/urpmi/helpers/urpmi_backend/open_db.pm
+:000000 100644 0000000... e078134... A backends/urpmi/helpers/urpmi_backend/tools.pm
+:000000 100644 0000000... e7b56a7... A backends/urpmi/pk-backend-urpmi.c
+:100644 100644 5b2da8f... d70d8dc... M backends/yum/helpers/yumBackend.py
+:100755 100755 29f5b03... a708a0c... M backends/yum2/helpers/yumDBUSBackend.py
+:100644 100644 15c4b4f... a971707... M backends/zypp/pk-backend-zypp.cpp
+:100644 100644 2b848f0... d81d0dd... M backends/zypp/zypp-utils.cpp
+:100644 100644 9e3bad1... 4f785cf... M backends/zypp/zypp-utils.h
+:100644 100644 5a05a8e... ec93978... M client/pk-console.c
+:100644 100644 f5be0a5... bfe364f... M client/pk-import-desktop.c
+:100644 100644 cf14cc2... bffd45b... M client/pk-import-specspo.c
+:100644 100644 f614d2b... 7510b03... M configure.ac
+:100644 100644 4d4a7e3... 61a67d1... M contrib/PackageKit.spec.in
+:100644 100644 a97fc3b... ded7799... M contrib/gnome-packagekit.spec.in
+:100644 100644 607a7a4... 7aa298b... M docs/html/pk-authors.html
+:100644 100644 0cdc85c... d276a05... M docs/html/pk-download.html
+:100644 100644 efa8344... 3e37cc1... M docs/html/pk-faq.html
+:100644 100644 0b75b10... 51a165a... M docs/spec/pk-concepts.xml
+:100644 100644 a79e647... 2970dda... M docs/spec/pk-signals.xml
+:100644 100644 8f9bd57... 7a48320... M etc/PackageKit.conf.in
+:100644 100644 dd2387b... 8fb82f1... M libpackagekit/pk-client.c
+:100644 100644 2b1d1a2... 6617159... M libpackagekit/pk-client.h
+:100644 100644 9d3cff7... 0be0e6e... M libpackagekit/pk-common.c
+:100644 100644 9908ec2... 9e5a05e... M libpackagekit/pk-common.h
+:100644 100644 f2de5ae... 5a54ccc... M libpackagekit/pk-control.c
+:100644 100644 63b30d3... c1b1be8... M libpackagekit/pk-control.h
+:100644 100644 5743dcb... 9dccdd0... M libpackagekit/pk-enum.c
+:100644 100644 e616b64... 4cc317e... M libpackagekit/pk-enum.h
+:100644 100644 7f01a4c... d0f0776... M libpackagekit/pk-extra.c
+:100644 100644 87905dc... ff4bd4e... M libpackagekit/pk-package-item.c
+:100644 100644 5d95e1b... 6bdb0d4... M libpackagekit/pk-package-list.c
+:100644 100644 9734af4... 83901ab... M libpackagekit/pk-package-list.h
+:100644 100644 dceb656... 7308a29... M libpackagekit/pk-polkit-client.c
+:100644 100644 76ab022... 3dc1db0... M libpackagekit/pk-task-list.c
+:100644 100644 6dbee0e... f87e6b3... M po/LINGUAS
+:100644 100644 33d30c1... 6e8013e... M po/de.po
+:000000 100644 0000000... ea732d0... A po/hu.po
+:100644 100644 32efce7... 4c4607d... M policy/org.freedesktop.packagekit.policy.in
+:100644 100644 5253b39... 9fd627a... M python/packagekit/daemonBackend.py
+:100644 100644 f9c9f12... 2bd416d... M src/pk-backend-spawn.c
+:100644 100644 37ed024... f0f245f... M src/pk-backend.c
+:100644 100644 fb17e3c... a7ba754... M src/pk-backend.h
+:100644 100644 028a0d0... 14ecf41... M src/pk-engine.c
+:100644 100644 c59b1f3... 668451f... M src/pk-engine.h
+:100644 100644 e9e74e1... 7290bbe... M src/pk-interface.xml
+:100644 100644 9abf992... 81332d0... M src/pk-security-polkit.c
+:100644 100644 3432095... eb55932... M src/pk-security.h
+:100644 100644 7aa183f... d42bc7a... M src/pk-transaction-db.c
+:100644 100644 0921c7c... f325f94... M src/pk-transaction-list.c
+:100644 100644 07ffdee... 15faed3... M src/pk-transaction.c
+:100755 100755 f78c891... 6521e69... M tools/add-error-enum.sh
+:100755 000000 ebbd8f7... 0000000... D tools/rpmbuild.sh
+
+diff --git a/RELEASE b/RELEASE
+new file mode 100644
+index 0000000..bd0cc2e
+--- /dev/null
++++ b/RELEASE
+@@ -0,0 +1,50 @@
++PackageKit Release Notes
++
++1. Write NEWS entries for PackageKit and gnome-packagekit in the same
++   format as usual. Ignore any trivial commits.
++
++$git-shortlog GNOME_PACKAGEKIT_0_2_1.. | grep -v trivial > NEWS.new
++
++2. Add download date to docs/html/pk-download.html, save file.
++
++3. Update library version if new ABI in configure.ac and change DEVELOPMENT_RELEASE if needed
++
++4. Commit changes in PackageKit git:
++
++$git commit -a -m "Release version 0.2.2"
++$git tag -a -f -m "Release 0.2.2" PACKAGEKIT_0_2_2
++$git push --tags
++$git push
++
++5. Commit changes in gnome-packagekit git:
++
++$git commit -a -m "Release version 0.2.2"
++$git-tag GNOME_PACKAGEKIT_0_2_2
++$git push --tags
++$git push
++
++6. Upload both tarballs to:
++
++$scp *.tar.gz packagekit.org/srv/www/html/releases/
++
++7. Do post release version bump in configure.ac
++
++8. Commit changes in both projects:
++
++$git commit -a -m "post release version bump"
++$git push
++
++9. Send an email to packagekit@lists.freedesktop.org
++
++=================================================
++Subject: PackageKit and gnome-packagekit 0.2.2 released!
++
++Today I released PackageKit and gnome-packagekit 0.2.2.
++
++PackageKit release notes: http://gitweb.freedesktop.org/?p=packagekit.git;a=blob;f=NEWS
++gnome-packagekit release notes: http://gitweb.freedesktop.org/?p=users/hughsient/gnome-packagekit.git;a=blob;f=NEWS
++
++Tarballs available here: http://people.freedesktop.org/~hughsient/releases/
++Thanks to all those who made this possible.
++=================================================
++
+diff --git a/backends/Makefile.am b/backends/Makefile.am
+index fcc8347..20279b3 100644
+--- a/backends/Makefile.am
++++ b/backends/Makefile.am
+@@ -8,10 +8,6 @@ if BACKEND_TYPE_APT
+ SUBDIRS += apt
+ endif
+-if BACKEND_TYPE_APT_DBUS
+-SUBDIRS += apt2
+-endif
+-
+ if BACKEND_TYPE_BOX
+ SUBDIRS += box
+ endif
+@@ -32,6 +28,10 @@ if BACKEND_TYPE_SMART
+ SUBDIRS += smart
+ endif
++if BACKEND_TYPE_URPMI
++SUBDIRS += urpmi
++endif
++
+ if BACKEND_TYPE_YUM
+ SUBDIRS += yum
+ endif
+diff --git a/backends/apt.deprecated/.gitignore b/backends/apt.deprecated/.gitignore
+new file mode 100644
+index 0000000..c851833
+--- /dev/null
++++ b/backends/apt.deprecated/.gitignore
+@@ -0,0 +1,10 @@
++.deps
++.libs
++Makefile
++Makefile.in
++*.la
++*.lo
++*.loT
++*.o
++*~
++
+diff --git a/backends/apt.deprecated/Makefile.am b/backends/apt.deprecated/Makefile.am
+new file mode 100644
+index 0000000..07b4131
+--- /dev/null
++++ b/backends/apt.deprecated/Makefile.am
+@@ -0,0 +1,30 @@
++NULL =
++
++SUBDIRS = helpers
++plugindir = $(PK_PLUGIN_DIR)
++plugin_LTLIBRARIES = libpk_backend_apt.la
++
++libpk_backend_apt_la_LIBADD = $(PK_PLUGIN_LIBS)
++libpk_backend_apt_la_LDFLAGS = -module -avoid-version $(APT_LIBS)
++libpk_backend_apt_la_CFLAGS = $(PK_PLUGIN_CFLAGS) $(APT_CFLAGS)
++libpk_backend_apt_la_CXXFLAGS = $(PK_PLUGIN_CFLAGS) $(APT_CFLAGS) -DPK_DB_DIR=\""$(PK_DB_DIR)"\"
++
++libpk_backend_apt_la_SOURCES =                                \
++      pk-backend-apt.c                                \
++      pk-apt-search.h                                 \
++      $(NULL)
++
++if APT_SEARCH_PLAIN
++libpk_backend_apt_la_SOURCES +=                               \
++      pk-apt-search-plain.c                           \
++      $(NULL)
++endif
++
++if APT_SEARCH_SQLITE
++libpk_backend_apt_la_SOURCES +=                               \
++      pk-sqlite-pkg-cache.h                           \
++      pk-sqlite-pkg-cache.cpp                         \
++      pk-apt-build-db.cpp                             \
++      pk-apt-search-sqlite.cpp                        \
++      $(NULL)
++endif
+diff --git a/backends/apt.deprecated/helpers/.gitignore b/backends/apt.deprecated/helpers/.gitignore
+new file mode 100644
+index 0000000..0d20b64
+--- /dev/null
++++ b/backends/apt.deprecated/helpers/.gitignore
+@@ -0,0 +1 @@
++*.pyc
+diff --git a/backends/apt.deprecated/helpers/Makefile.am b/backends/apt.deprecated/helpers/Makefile.am
+new file mode 100644
+index 0000000..0299df2
+--- /dev/null
++++ b/backends/apt.deprecated/helpers/Makefile.am
+@@ -0,0 +1,29 @@
++
++helperdir = $(datadir)/PackageKit/helpers/apt
++
++NULL =
++
++dist_helper_DATA =                    \
++      install-files.py                \
++      search-name.py                  \
++      search-details.py               \
++      search-group.py                 \
++      search-file.py                  \
++      get-depends.py                  \
++      get-details.py                  \
++      get-repo-list.py                \
++      get-requires.py                 \
++      get-update-detail.py            \
++      get-updates.py                  \
++      refresh-cache.py                \
++      repo-enable.py                  \
++      resolve.py                      \
++      aptBackend.py                   \
++      $(NULL)
++
++install-data-hook:
++      chmod a+rx $(DESTDIR)$(helperdir)/*.py
++
++clean-local :
++      rm -f *~
++
+diff --git a/backends/apt.deprecated/helpers/aptBackend.py b/backends/apt.deprecated/helpers/aptBackend.py
+new file mode 100644
+index 0000000..e5f78ca
+--- /dev/null
++++ b/backends/apt.deprecated/helpers/aptBackend.py
+@@ -0,0 +1,536 @@
++#
++# vim: ts=4 et sts=4
++#
++# Copyright (C) 2007 Ali Sabil <ali.sabil@gmail.com>
++# Copyright (C) 2007 Tom Parker <palfrey@tevp.net>
++#
++# Licensed under the GNU General Public License Version 2
++#
++# 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 2 of the License, or
++# (at your option) any later version.
++
++import sys
++import os
++import re
++
++from packagekit.backend import *
++import apt_pkg,apt_inst
++
++import warnings
++warnings.filterwarnings(action='ignore', category=FutureWarning)
++import apt
++from aptsources.distro import get_distro
++from aptsources.sourceslist import SourcesList
++from sets import Set
++from os.path import join,exists
++from urlparse import urlparse
++from apt.debfile import DebPackage
++from os import system
++
++class Package(apt.Package):
++    def __str__(self):
++        return "Package %s, version %s"%(self.name,self._version)
++
++    def _cmp_deps(self,deps, version):
++        for (v,c) in deps:
++            if not apt_pkg.CheckDep(version,c,v):
++                return False
++        return True
++
++    def __init__(self, backend, pkg, data="",version=[]):
++        apt.package.Package.__init__(self, pkg._cache, pkg._depcache,
++                                     pkg._records, pkg._list, pkg._pcache,
++                                     pkg._pkg)
++        self._version = version
++        self._data = data
++        self._backend = backend
++        wanted_ver = None
++        if self.installedVersion!=None and self._cmp_deps(version,self.installedVersion):
++            wanted_ver = self.installedVersion
++        elif self.installedVersion == None and version == []:
++            #self.markInstall(False,False)
++            wanted_ver = self.candidateVersion
++
++        for ver in pkg._pkg.VersionList:
++            #print "vers",dir(ver),version,ver
++            #print data
++            if (wanted_ver == None or wanted_ver == ver.VerStr) and self._cmp_deps(version,ver.VerStr):
++                f, index = ver.FileList.pop(0)
++                if self._data == "":
++                    if f.Origin=="" and f.Archive=="now":
++                        self._data = "local_install"
++                    elif f.Origin!="" or f.Archive!="":
++                        self._data = "%s/%s"%(f.Origin.replace("/","_"),f.Archive.replace("/","_"))
++                    else:
++                        self._data = "%s/unknown"%f.Site
++                self._version = ver.VerStr
++                break
++        else:
++            print "wanted",wanted_ver
++            for ver in pkg._pkg.VersionList:
++                print "vers",version,ver.VerStr
++            backend.error(ERROR_PACKAGE_NOT_FOUND, "Can't find version %s for %s"%(version,self.name))
++
++    def setVersion(self,version,compare="="):
++        if version!=None and (self.installedVersion == None or not apt_pkg.CheckDep(version,compare,self.installedVersion)):
++            self.markInstall(False,False)
++            if self.candidateVersion != version:
++                if self._data == "":
++                    for ver in pkg._pkg.VersionList:
++                        f, index = ver.FileList.pop(0)
++                        self._data = "%s/%s"%(f.Origin,f.Archive)
++                        if ver.VerStr == version:
++                            break
++
++                # FIXME: this is a nasty hack, assuming that the best way to resolve
++                # deps for non-default repos is by switching the default release.
++                # We really need a better resolver (but that's hard)
++                assert self._data!=""
++                origin = self._data[self._data.find("/")+1:]
++                print "origin",origin
++                name = self.name
++                apt_pkg.Config.Set("APT::Default-Release",origin)
++                if not self._backend._caches.has_key(origin):
++                    self._backend._caches[origin] = apt.Cache(PackageKitProgress(self))
++                    print "new cache for %s"%origin
++                self.__setParent(self._backend._caches[origin][name])
++                self.markInstall(False,False)
++                if not apt_pkg.CheckDep(self.candidateVersion,compare,version):
++                    self._backend.error(ERROR_PACKAGE_NOT_FOUND,
++                            "Unable to locate package version %s (only got %s) for %s"%(version,self.candidateVersion,name))
++                    return
++                self.markKeep()
++
++    @property
++    def group(self):
++        section = self.section.split('/')[-1].lower()
++        #if section in ():
++        #    return GROUP_ACCESSIBILITY
++        if section in ('utils',):
++            return "accessories"
++        #if section in ():
++        #    return GROUP_EDUCATION
++        if section in ('games',):
++            return "games"
++        if section in ('graphics',):
++            return "graphics"
++        if section in ('net', 'news', 'web', 'comm'):
++            return "internet"
++        if section in ('editors', 'tex'):
++            return "office"
++        if section in ('misc',):
++            return "other"
++        if section in ('devel', 'libdevel', 'interpreters', 'perl', 'python'):
++            return "programming"
++        if section in ('sound',):
++            return "multimedia"
++        if section in ('base', 'admin'):
++            return "system"
++        return "unknown"
++
++    @property
++    def isInstalled(self):
++        return super(self.__class__,self).isInstalled and self.installedVersion == self._version
++
++    @property
++    def isDevelopment(self):
++        name = self.name.lower()
++        section = self.section.split('/')[-1].lower()
++        return name.endswith('-dev') or name.endswith('-dbg') or \
++                section in ('devel', 'libdevel')
++
++    @property
++    def isGui(self):
++        section = self.section.split('/')[-1].lower()
++        return section in ('x11', 'gnome', 'kde')
++
++    _HYPHEN_PATTERN = re.compile(r'(\s|_)+')
++
++    def matchName(self, name):
++        needle = name.strip().lower()
++        haystack = self.name.lower()
++        needle = Package._HYPHEN_PATTERN.sub('-', needle)
++        haystack = Package._HYPHEN_PATTERN.sub('-', haystack)
++        if haystack.find(needle) >= 0:
++            return True
++        return False
++
++    def matchDetails(self, details):
++        if self.matchName(details):
++            return True
++        needle = details.strip().lower()
++        haystack = self.description.lower()
++        if haystack.find(needle) >= 0:
++            return True
++        return False
++
++    def matchGroup(self, name):
++        needle = name.strip().lower()
++        haystack = self.group
++        if haystack.startswith(needle):
++            return True
++        return False
++
++class PackageKitProgress(apt.progress.OpProgress, apt.progress.FetchProgress):
++    def __init__(self, backend):
++        self._backend = backend
++        apt.progress.OpProgress.__init__(self)
++        apt.progress.FetchProgress.__init__(self)
++
++    # OpProgress callbacks
++    def update(self, percent):
++        pass
++
++    def done(self):
++        pass
++
++    # FetchProgress callbacks
++    def pulse(self):
++        apt.progress.FetchProgress.pulse(self)
++        self._backend.percentage(self.percent)
++        return True
++
++    def stop(self):
++        self._backend.percentage(100)
++
++    def mediaChange(self, medium, drive):
++        # This probably should not be an error, but a Message.
++        self._backend.error(ERROR_UNKNOWN,
++                "Medium change needed")
++
++class PackageKitAptBackend(PackageKitBaseBackend):
++    def __init__(self, args):
++        PackageKitBaseBackend.__init__(self, args)
++        self.status(STATUS_SETUP)
++        self._caches  = {}
++        self._apt_cache = apt.Cache(PackageKitProgress(self))
++        default = apt_pkg.Config.Find("APT::Default-Release")
++        if default=="":
++            d = get_distro()
++            if d.id == "Debian":
++                default = "stable"
++            elif d.id == "Ubuntu":
++                default = "main"
++            else:
++                raise Exception,d.id
++
++        self._caches[default] = self._apt_cache
++
++
++    def search_name(self, filters, key):
++        '''
++        Implement the {backend}-search-name functionality
++        '''
++        self.status(STATUS_INFO)
++        self.allow_cancel(True)
++        for package in self._do_search(filters,
++                lambda pkg: pkg.matchName(key)):
++            self._emit_package(package)
++
++    def search_details(self, filters, key):
++        '''
++        Implement the {backend}-search-details functionality
++        '''
++        self.status(STATUS_INFO)
++        self.allow_cancel(True)
++        for package in self._do_search(filters,
++                lambda pkg: pkg.matchDetails(key)):
++            self._emit_package(package)
++
++    def search_group(self, filters, key):
++        '''
++        Implement the {backend}-search-group functionality
++        '''
++        self.status(STATUS_INFO)
++        self.allow_cancel(True)
++        for package in self._do_search(filters,
++                lambda pkg: pkg.matchGroup(key)):
++            self._emit_package(package)
++
++    def search_file(self, filters, key):
++        '''
++        Implement the {backend}-search-file functionality
++        '''
++        self.allow_cancel(True)
++        self.percentage(None)
++
++        self.error(ERROR_NOT_SUPPORTED,
++                "This function is not implemented in this backend")
++
++    def refresh_cache(self):
++        '''
++        Implement the {backend}-refresh_cache functionality
++        '''
++        self.status(STATUS_REFRESH_CACHE)
++        try:
++            res = self._apt_cache.update(PackageKitProgress(self))
++        except Exception, error_message:
++             self.error(ERROR_UNKNOWN,
++                        "Failed to fetch the following items:\n%s" % error_message)
++        return res
++
++    def get_details(self, package):
++        '''
++        Implement the {backend}-get-details functionality
++        '''
++        self.status(STATUS_INFO)
++        name, version, arch, data = self.get_package_from_id(package)
++        pkg = Package(self, self._apt_cache[name])
++        description = re.sub('\s+', ' ', pkg.description).strip()
++        self.description(package, 'unknown', pkg.group, description,
++                         pkg.architecture, pkg.packageSize)
++
++    def resolve(self, name):
++        '''
++        Implement the {backend}-resolve functionality
++        '''
++        self.status(STATUS_INFO)
++        try:
++            pkg = Package(self,self._apt_cache[name])
++            self._emit_package(pkg)
++        except KeyError:
++            self.error(ERROR_PACKAGE_NOT_FOUND,"Can't find a package called '%s'"%name)
++
++    def _do_deps(self,inp,deps,recursive):
++        inp.markInstall()
++        newkeys = []
++        for x in inp.candidateDependencies:
++            n = x.or_dependencies[0].name
++            if not deps.has_key(n):
++                deps[n] = []
++                newkeys.append(n)
++            deps[n].append((x.or_dependencies[0].version,x.or_dependencies[0].relation))
++        if recursive:
++            for n in newkeys:
++                try:
++                    deps = self._do_deps(Package(self,self._apt_cache[n],version=deps[n]),deps,recursive)
++                except KeyError: # FIXME: we're assuming this is a virtual package, which we can't cope with yet
++                    del deps[n]
++                    continue
++        return deps
++
++    def get_depends(self,filters,package, recursive):
++        '''
++        Implement the {backend}-get-depends functionality
++        '''
++        self.allow_cancel(True)
++        self.status(STATUS_INFO)
++        recursive = (recursive == "True")
++        name, version, arch, data = self.get_package_from_id(package)
++        pkg = Package(self,self._apt_cache[name],version=[(version,"=")],data=data)
++        pkg.setVersion(version)
++        deps = self._do_deps(pkg, {}, recursive)
++        for n in deps.keys():
++           self._emit_package(Package(self,self._apt_cache[n],version=deps[n]))
++
++    def _do_reqs(self,inp,pkgs,recursive):
++        extra = []
++        fails = []
++        for r in inp._pkg.RevDependsList:
++            ch = apt_pkg.CheckDep(inp._version,r.CompType,r.TargetVer)
++            v = (r.ParentPkg.Name,r.ParentVer.VerStr)
++            if not ch or v in fails:
++                #print "skip",r.TargetVer,r.CompType,r.ParentPkg.Name,r.ParentVer.VerStr
++                fails.append(v)
++                continue
++            p = Package(self,self._apt_cache[r.ParentPkg.Name],r.ParentVer.VerStr)
++            if v not in pkgs:
++                extra.append(p)
++                #print "new pkg",p
++                self._emit_package(p)
++            pkgs.add(v)
++        if recursive:
++            for e in extra:
++                pkgs = self._do_reqs(p, pkgs,recursive)
++        return pkgs
++
++    def get_requires(self,package,recursive):
++        '''
++        Implement the {backend}-get-requires functionality
++        '''
++        self.allow_cancel(True)
++        self.status(STATUS_INFO)
++        recursive = (recursive == "True")
++        name, version, arch, data = self.get_package_from_id(package)
++        pkg = Package(self,self._apt_cache[name], version=[(version,"=")], data=data)
++
++        pkgs = Set()
++        self._do_reqs(pkg,pkgs, recursive)
++
++    def _build_repo_list(self):
++        repo = {}
++
++        sources = SourcesList()
++        repo["__sources"] = sources
++
++        root = apt_pkg.Config.FindDir("Dir::State::Lists")
++        #print root
++        for entry in sources:
++            if entry.type!="":
++                url = entry.uri
++                #if entry.template!=None:
++                url +="/dists/"
++                url += entry.dist
++                url = url.replace("//dists","/dists")
++                #print url
++                path = join(root,"%s_Release"%(apt_pkg.URItoFileName(url)))
++                if not exists(path):
++                    #print path
++                    name = "%s/unknown"%urlparse(entry.uri)[1]
++                else:
++                    lines = file(path).readlines()
++                    origin = ""
++                    suite = ""
++                    for l in lines:
++                        if l.find("Origin: ")==0:
++                            origin = l.split(" ",1)[1].strip()
++                        elif l.find("Suite: ")==0:
++                            suite = l.split(" ",1)[1].strip()
++                    assert origin!="" and suite!=""
++                    name = "%s/%s"%(origin,suite)
++                if entry.type == "deb-src":
++                    name += "-src"
++
++                repo[name] = {"entry":entry}
++        return repo
++
++    def get_repo_list(self, filters):
++        '''
++        Implement the {backend}-get-repo-list functionality
++        '''
++        self.allow_interrupt(True)
++        self.status(STATUS_INFO)
++        repo = self._build_repo_list()
++        for e in repo.keys():
++            if e == "__sources":
++                continue
++            self.repo_detail(repo[e]["entry"].line.strip(),e,not repo[e]["entry"].disabled)
++
++    def repo_enable(self, repoid, enable):
++        '''
++        Implement the {backend}-repo-enable functionality
++        '''
++        enable = (enable == "True")
++        repo = self._build_repo_list()
++        if not repo.has_key(repoid):
++            self.error(ERROR_REPO_NOT_FOUND,"Couldn't find repo '%s'"%repoid)
++            return
++        r = repo[repoid]
++        if not r["entry"].disabled == enable: # already there
++            return
++        r["entry"].set_enabled(enable)
++        try:
++            repo["__sources"].save()
++        except IOError,e:
++            self.error(ERROR_UNKNOWN, "Problem while trying to save repo settings to %s: %s"%(e.filename,e.strerror))
++
++    def get_updates(self, filter):
++        self._apt_cache.upgrade(False)
++        for pkg in self._apt_cache.getChanges():
++            self._emit_package(Package(self, pkg))
++
++    def get_update_detail(self, package):
++        self.allow_cancel(True)
++        self.percentage(None)
++        self.status(STATUS_INFO)
++        name, version, arch, data = self.get_package_from_id(package)
++        update = ""
++        obsolete = ""
++        cve_url = ""
++        bz_url = ""
++        vendor_url = ""
++        reboot = "none"
++        desc = self._apt_cache[name].description
++        self.update_detail(package,update,obsolete,vendor_url,bz_url,cve_url,reboot,desc)
++
++
++    def install_files (self, inst_files):
++        '''
++        Implement the {backend}-install_files functionality
++        Install the package containing the inst_file file
++        '''
++        if not exists(inst_file):
++            self.error(ERROR_PACKAGE_NOT_FOUND,"Can't find %s"%inst_file)
++            return
++        deb = DebPackage(inst_file)
++        deps = {}
++        for k in ["Depends","Recommends"]:
++            if not deb._sections.has_key(k):
++                continue
++            for items in apt_pkg.ParseDepends(deb[k]):
++                assert len(items) == 1,"Can't handle or deps properly yet"
++                (pkg,ver,comp) = items[0]
++                if not deps.has_key(pkg):
++                    deps[pkg] = []
++                deps[pkg].append((ver,comp))
++        for n in deps.keys():
++           p = Package(self,self._apt_cache[n],version=deps[n])
++           if not p.isInstalled:
++               p.markInstall()
++        assert self._apt_cache.getChanges()==[],"Don't handle install changes yet"
++        # FIXME: nasty hack. Need a better way in
++        ret = system("dpkg -i %s"%inst_file)
++        if ret!=0:
++            self.error(ERROR_UNKNOWN,"Can't install package")
++
++    ### Helpers ###
++    def _emit_package(self, package):
++        id = self.get_package_id(package.name,
++                package._version,
++                package.architecture,
++                package._data)
++        if package.isInstalled:
++            status = INFO_INSTALLED
++        else:
++            status = INFO_AVAILABLE
++        summary = package.summary
++        self.package(id, status, summary)
++
++    def _do_search(self, filters, condition):
++        filters = filters.split(';')
++        size = len(self._apt_cache)
++        percentage = 0
++        for i, pkg in enumerate(self._apt_cache):
++            new_percentage = i / float(size) * 100
++            if new_percentage - percentage >= 5:
++                percentage = new_percentage
++                self.percentage(percentage)
++            package = Package(self, pkg)
++            if package.installedVersion is None and \
++                    package.candidateVersion is None:
++                continue
++            if not condition(package):
++                continue
++                continue
++            vers = [x.VerStr for x in package._pkg.VersionList]
++            if package.installedVersion!=None:
++                i = package.installedVersion
++                if i in vers and vers[0]!=i:
++                    del vers[vers.index(i)]
++                    vers.insert(0,i)
++
++            for ver in vers:
++                p = Package(self, package, version=[[ver,"="]])
++                if self._do_filtering(p, filters):
++                    yield p
++        self.percentage(100)
++
++    def _do_filtering(self, package, filters):
++        if len(filters) == 0 or filters == ['none']:
++            return True
++        if (FILTER_INSTALLED in filters) and (not package.isInstalled):
++            return False
++        if (FILTER_NOT_INSTALLED in filters) and package.isInstalled:
++            return False
++        if (FILTER_GUI in filters) and (not package.isGui):
++            return False
++        if (FILTER_NOT_GUI in filters) and package.isGui:
++            return False
++        if (FILTER_DEVELOPMENT in filters) and (not package.isDevelopment):
++            return False
++        if (FILTER_NOT_DEVELOPMENT in filters) and package.isDevelopment:
++            return False
++        return True
++
+diff --git a/backends/apt.deprecated/helpers/get-depends.py b/backends/apt.deprecated/helpers/get-depends.py
+new file mode 100755
+index 0000000..94dca4a
+--- /dev/null
++++ b/backends/apt.deprecated/helpers/get-depends.py
+@@ -0,0 +1,20 @@
++#!/usr/bin/python
++#
++# Copyright (C) 2007 Richard Hughes <richard@hughsie.com>
++#
++# Licensed under the GNU General Public License Version 2
++#
++# 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 2 of the License, or
++# (at your option) any later version.
++
++import sys
++
++from aptBackend import PackageKitAptBackend
++filters=sys.argv[1]
++package=sys.argv[2]
++recursive = sys.argv[3]
++backend = PackageKitAptBackend(sys.argv[1:])
++backend.get_depends(filters, package, recursive)
++sys.exit(0)
+diff --git a/backends/apt.deprecated/helpers/get-details.py b/backends/apt.deprecated/helpers/get-details.py
+new file mode 100755
+index 0000000..a813640
+--- /dev/null
++++ b/backends/apt.deprecated/helpers/get-details.py
+@@ -0,0 +1,18 @@
++#!/usr/bin/python
++#
++# Copyright (C) 2007 Ali Sabil <ali.sabil@gmail.com>
++#
++# Licensed under the GNU General Public License Version 2
++#
++# 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 2 of the License, or
++# (at your option) any later version.
++
++import sys
++from aptBackend import PackageKitAptBackend
++
++package = sys.argv[1]
++backend = PackageKitAptBackend(sys.argv[1:])
++backend.get_details(package)
++sys.exit(0)
+diff --git a/backends/apt.deprecated/helpers/get-repo-list.py b/backends/apt.deprecated/helpers/get-repo-list.py
+new file mode 100755
+index 0000000..5529f72
+--- /dev/null
++++ b/backends/apt.deprecated/helpers/get-repo-list.py
+@@ -0,0 +1,20 @@
++#!/usr/bin/python
++#
++# Copyright (C) 2007 Richard Hughes <richard@hughsie.com>
++#
++# Licensed under the GNU General Public License Version 2
++#
++# 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 2 of the License, or
++# (at your option) any later version.
++
++import sys
++
++from aptBackend import PackageKitAptBackend
++filters = sys.argv[1]
++
++backend = PackageKitAptBackend(sys.argv[2:])
++backend.get_repo_list(filters)
++backend.unLock()
++sys.exit(0)
+diff --git a/backends/apt.deprecated/helpers/get-requires.py b/backends/apt.deprecated/helpers/get-requires.py
+new file mode 100755
+index 0000000..e581010
+--- /dev/null
++++ b/backends/apt.deprecated/helpers/get-requires.py
+@@ -0,0 +1,20 @@
++#!/usr/bin/python
++#
++# Copyright (C) 2007 Richard Hughes <richard@hughsie.com>
++#
++# Licensed under the GNU General Public License Version 2
++#
++# 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 2 of the License, or
++# (at your option) any later version.
++
++import sys
++
++from aptBackend import PackageKitAptBackend
++package = sys.argv[1]
++recursive = sys.argv[2]
++
++backend = PackageKitAptBackend(sys.argv[1:])
++backend.get_requires(package, recursive)
++sys.exit(0)
+diff --git a/backends/apt.deprecated/helpers/get-update-detail.py b/backends/apt.deprecated/helpers/get-update-detail.py
+new file mode 100755
+index 0000000..5524d9a
+--- /dev/null
++++ b/backends/apt.deprecated/helpers/get-update-detail.py
+@@ -0,0 +1,18 @@
++#!/usr/bin/python
++#
++# Copyright (C) 2008 Michael Vogt <mvo@ubuntu.com>
++#
++# Licensed under the GNU General Public License Version 2
++#
++# 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 2 of the License, or
++# (at your option) any later version.
++
++import sys
++
++from aptBackend import PackageKitAptBackend
++package=sys.argv[1]
++backend = PackageKitAptBackend(sys.argv[2:])
++backend.get_update_detail(package)
++sys.exit(0)
+diff --git a/backends/apt.deprecated/helpers/get-updates.py b/backends/apt.deprecated/helpers/get-updates.py
+new file mode 100755
+index 0000000..4f45fbf
+--- /dev/null
++++ b/backends/apt.deprecated/helpers/get-updates.py
+@@ -0,0 +1,19 @@
++#!/usr/bin/python
++#
++# Copyright (C) 2008 Michael Vogt <mvo@ubuntu.com>
++#
++# Licensed under the GNU General Public License Version 2
++#
++# 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 2 of the License, or
++# (at your option) any later version.
++
++import sys
++from aptBackend import PackageKitAptBackend
++
++filter = sys.argv[1]
++
++backend = PackageKitAptBackend(sys.argv[1:])
++backend.get_updates(filter)
++sys.exit(0)
+diff --git a/backends/apt.deprecated/helpers/install-files.py b/backends/apt.deprecated/helpers/install-files.py
+new file mode 100755
+index 0000000..dfa024c
+--- /dev/null
++++ b/backends/apt.deprecated/helpers/install-files.py
+@@ -0,0 +1,21 @@
++#!/usr/bin/python
++#
++# Copyright (C) 2007 Richard Hughes <richard@hughsie.com>
++# Copyright (C) 2007 Red Hat Inc, Seth Vidal <skvidal@fedoraproject.org>
++#
++# Licensed under the GNU General Public License Version 2
++#
++# 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 2 of the License, or
++# (at your option) any later version.
++
++import sys
++
++from aptBackend import PackageKitAptBackend
++
++trusted = sys.argv[1]
++files_to_inst = sys.argv[2:]
++backend = PackageKitAptBackend(sys.argv[1:])
++backend.install_files(trusted, files_to_inst)
++sys.exit(0)
+diff --git a/backends/apt.deprecated/helpers/packagekit b/backends/apt.deprecated/helpers/packagekit
+new file mode 120000
+index 0000000..8d22531
+--- /dev/null
++++ b/backends/apt.deprecated/helpers/packagekit
+@@ -0,0 +1 @@
++../../../python/packagekit
+\ No newline at end of file
+diff --git a/backends/apt.deprecated/helpers/refresh-cache.py b/backends/apt.deprecated/helpers/refresh-cache.py
+new file mode 100755
+index 0000000..881479d
+--- /dev/null
++++ b/backends/apt.deprecated/helpers/refresh-cache.py
+@@ -0,0 +1,17 @@
++#!/usr/bin/python
++#
++# Copyright (C) 2007 Ali Sabil <ali.sabil@gmail.com>
++#
++# Licensed under the GNU General Public License Version 2
++#
++# 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 2 of the License, or
++# (at your option) any later version.
++
++import sys
++from aptBackend import PackageKitAptBackend
++
++backend = PackageKitAptBackend(sys.argv[1:])
++backend.refresh_cache()
++sys.exit(0)
+diff --git a/backends/apt.deprecated/helpers/repo-enable.py b/backends/apt.deprecated/helpers/repo-enable.py
+new file mode 100755
+index 0000000..3cc36ae
+--- /dev/null
++++ b/backends/apt.deprecated/helpers/repo-enable.py
+@@ -0,0 +1,20 @@
++#!/usr/bin/python
++#
++# Copyright (C) 2007 Richard Hughes <richard@hughsie.com>
++#
++# Licensed under the GNU General Public License Version 2
++#
++# 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 2 of the License, or
++# (at your option) any later version.
++
++import sys
++
++from aptBackend import PackageKitAptBackend
++repoid = sys.argv[1]
++state=sys.argv[2]
++backend = PackageKitAptBackend(sys.argv[2:])
++backend.repo_enable(repoid,state)
++backend.unLock()
++sys.exit(0)
+diff --git a/backends/apt.deprecated/helpers/resolve.py b/backends/apt.deprecated/helpers/resolve.py
+new file mode 100755
+index 0000000..aac34df
+--- /dev/null
++++ b/backends/apt.deprecated/helpers/resolve.py
+@@ -0,0 +1,20 @@
++#!/usr/bin/python
++#
++# Copyright (C) 2007 Richard Hughes <richard@hughsie.com>
++#
++# Licensed under the GNU General Public License Version 2
++#
++# 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 2 of the License, or
++# (at your option) any later version.
++
++import sys
++
++from aptBackend import PackageKitAptBackend
++filters = sys.argv[1]
++name=sys.argv[2]
++backend = PackageKitAptBackend(sys.argv[2:])
++backend.resolve(name)
++backend.unLock()
++sys.exit(0)
+diff --git a/backends/apt.deprecated/helpers/search-details.py b/backends/apt.deprecated/helpers/search-details.py
+new file mode 100755
+index 0000000..d02f1b0
+--- /dev/null
++++ b/backends/apt.deprecated/helpers/search-details.py
+@@ -0,0 +1,21 @@
++#!/usr/bin/python
++#
++# Copyright (C) 2007 Ali Sabil <ali.sabil@gmail.com>
++#
++# Licensed under the GNU General Public License Version 2
++#
++# 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 2 of the License, or
++# (at your option) any later version.
++
++import sys
++
++options = sys.argv[1]
++searchlist = sys.argv[2]
++
++from aptBackend import PackageKitAptBackend
++
++backend = PackageKitAptBackend(sys.argv[1:])
++backend.search_details(options,searchlist)
++sys.exit(0)
+diff --git a/backends/apt.deprecated/helpers/search-file.py b/backends/apt.deprecated/helpers/search-file.py
+new file mode 100755
+index 0000000..ec60319
+--- /dev/null
++++ b/backends/apt.deprecated/helpers/search-file.py
+@@ -0,0 +1,21 @@
++#!/usr/bin/python
++#
++# Copyright (C) 2007 Ali Sabil <ali.sabil@gmail.com>
++#
++# Licensed under the GNU General Public License Version 2
++#
++# 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 2 of the License, or
++# (at your option) any later version.
++
++import sys
++
++options = sys.argv[1]
++searchlist = sys.argv[2]
++
++from aptBackend import PackageKitAptBackend
++
++backend = PackageKitAptBackend(sys.argv[1:])
++backend.search_file(options,searchlist)
++sys.exit(0)
+diff --git a/backends/apt.deprecated/helpers/search-group.py b/backends/apt.deprecated/helpers/search-group.py
+new file mode 100755
+index 0000000..f63ee80
+--- /dev/null
++++ b/backends/apt.deprecated/helpers/search-group.py
+@@ -0,0 +1,21 @@
++#!/usr/bin/python
++#
++# Copyright (C) 2007 Ali Sabil <ali.sabil@gmail.com>
++#
++# Licensed under the GNU General Public License Version 2
++#
++# 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 2 of the License, or
++# (at your option) any later version.
++
++import sys
++
++options = sys.argv[1]
++searchlist = sys.argv[2]
++
++from aptBackend import PackageKitAptBackend
++
++backend = PackageKitAptBackend(sys.argv[1:])
++backend.search_group(options,searchlist)
++sys.exit(0)
+diff --git a/backends/apt.deprecated/helpers/search-name.py b/backends/apt.deprecated/helpers/search-name.py
+new file mode 100755
+index 0000000..9f73c89
+--- /dev/null
++++ b/backends/apt.deprecated/helpers/search-name.py
+@@ -0,0 +1,21 @@
++#!/usr/bin/python
++#
++# Copyright (C) 2007 Ali Sabil <ali.sabil@gmail.com>
++#
++# Licensed under the GNU General Public License Version 2
++#
++# 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 2 of the License, or
++# (at your option) any later version.
++
++import sys
++
++options = sys.argv[1]
++searchlist = sys.argv[2]
++
++from aptBackend import PackageKitAptBackend
++
++backend = PackageKitAptBackend(sys.argv[1:])
++backend.search_name(options,searchlist)
++sys.exit(0)
+diff --git a/backends/apt.deprecated/pk-apt-build-db.cpp b/backends/apt.deprecated/pk-apt-build-db.cpp
+new file mode 100644
+index 0000000..885275d
+--- /dev/null
++++ b/backends/apt.deprecated/pk-apt-build-db.cpp
+@@ -0,0 +1,284 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
++ *
++ * Copyright (C) 2007 Tom Parker <palfrey@tevp.net>
++ *
++ * Licensed under the GNU General Public License Version 2
++ *
++ * 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 2 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, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++//#include "pk-backend-apt.h"
++#include <pk-backend.h>
++#include <apt-pkg/configuration.h>
++#include <sqlite3.h>
++
++typedef enum {FIELD_PKG=1,FIELD_VER,FIELD_DEPS,FIELD_ARCH,FIELD_SHORT,FIELD_LONG,FIELD_REPO} Fields;
++
++void apt_build_db(PkBackend * backend, sqlite3 *db)
++{
++      GMatchInfo *match_info;
++      GError *error = NULL;
++      gchar *contents = NULL;
++      gchar *sdir;
++      const gchar *fname;
++      GRegex *origin, *suite;
++      GDir *dir;
++      GHashTable *releases;
++      int res;
++      sqlite3_stmt *package = NULL;
++
++      pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY);
++      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
++
++      sdir = g_build_filename(_config->Find("Dir").c_str(),_config->Find("Dir::State").c_str(),_config->Find("Dir::State::lists").c_str(), NULL);
++      dir = g_dir_open(sdir,0,&error);
++      if (error!=NULL)
++      {
++              pk_backend_error_code(backend, PK_ERROR_ENUM_INTERNAL_ERROR, "can't open %s",dir);
++              g_error_free(error);
++              goto search_task_cleanup;
++      }
++
++      origin = g_regex_new("^Origin: (\\S+)",(GRegexCompileFlags)(G_REGEX_CASELESS|G_REGEX_OPTIMIZE|G_REGEX_MULTILINE),(GRegexMatchFlags)0,NULL);
++      suite = g_regex_new("^Suite: (\\S+)",(GRegexCompileFlags)(G_REGEX_CASELESS|G_REGEX_OPTIMIZE|G_REGEX_MULTILINE),(GRegexMatchFlags)0,NULL);
++
++      releases = g_hash_table_new_full(g_str_hash,g_str_equal,g_free,g_free);
++      while ((fname = g_dir_read_name(dir))!=NULL)
++      {
++              gchar *temp, *parsed_name;
++              gchar** items = g_strsplit(fname,"_",-1);
++              guint len = g_strv_length(items);
++              if(len<=3) // minimum is <source>_<type>_<group>
++              {
++                      g_strfreev(items);
++                      continue;
++              }
++
++              /* warning: nasty hack with g_strjoinv */
++              temp = items[len-2];
++              items[len-2] = NULL;
++              parsed_name = g_strjoinv("_",items);
++              items[len-2] = temp;
++
++              if (g_ascii_strcasecmp(items[len-1],"Release")==0 && g_ascii_strcasecmp(items[len-2],"source")!=0)
++              {
++                      gchar * repo = NULL, *fullname;
++                      fullname = g_build_filename(sdir,fname,NULL);
++                      if (g_file_get_contents(fullname,&contents,NULL,NULL) == FALSE)
++                      {
++                              pk_backend_error_code(backend, PK_ERROR_ENUM_INTERNAL_ERROR, "error loading %s",fullname);
++                              goto search_task_cleanup;
++                      }
++                      g_free(fullname);
++
++                      g_regex_match (origin, contents, (GRegexMatchFlags)0, &match_info);
++                      if (!g_match_info_matches(match_info))
++                      {
++                              pk_backend_error_code(backend, PK_ERROR_ENUM_INTERNAL_ERROR, "origin regex failure in %s",fname);
++                              goto search_task_cleanup;
++                      }
++                      repo = g_match_info_fetch (match_info, 1);
++
++                      g_regex_match (suite, contents, (GRegexMatchFlags)0, &match_info);
++                      if (g_match_info_matches(match_info))
++                      {
++                              temp = g_strconcat(repo,"/",g_match_info_fetch (match_info, 1),NULL);
++                              g_free(repo);
++                              repo = temp;
++                      }
++
++                      temp = parsed_name;
++                      parsed_name = g_strconcat(temp,"_",items[len-2],NULL);
++                      g_free(temp);
++
++                      pk_debug("type is %s, group is %s, parsed_name is %s",items[len-2],items[len-1],parsed_name);
++
++                      g_hash_table_insert(releases, parsed_name, repo);
++                      g_free(contents);
++                      contents = NULL;
++              }
++              else
++                      g_free(parsed_name);
++              g_strfreev(items);
++      }
++      g_dir_close(dir);
++
++      /* and then we need to do this again, but this time we're looking for the packages */
++      dir = g_dir_open(sdir,0,&error);
++      res = sqlite3_prepare_v2(db, "insert or replace into packages values (?,?,?,?,?,?,?)", -1, &package, NULL);
++      if (res!=SQLITE_OK)
++              pk_error("sqlite error during insert prepare: %s", sqlite3_errmsg(db));
++      else
++              pk_debug("insert prepare ok for %p",package);
++      while ((fname = g_dir_read_name(dir))!=NULL)
++      {
++              gchar** items = g_strsplit(fname,"_",-1);
++              guint len = g_strv_length(items);
++              if(len<=3) // minimum is <source>_<type>_<group>
++              {
++                      g_strfreev(items);
++                      continue;
++              }
++
++              if (g_ascii_strcasecmp(items[len-1],"Packages")==0)
++              {
++                      const gchar *repo;
++                      gchar *temp=NULL, *parsed_name=NULL;
++                      gchar *fullname= NULL;
++                      gchar *begin=NULL, *next=NULL, *description = NULL;
++                      glong count = 0;
++                      gboolean haspk = FALSE;
++
++                      /* warning: nasty hack with g_strjoinv */
++                      if (g_str_has_prefix(items[len-2],"binary-"))
++                      {
++                              temp = items[len-3];
++                              items[len-3] = NULL;
++                              parsed_name = g_strjoinv("_",items);
++                              items[len-3] = temp;
++                      }
++                      else
++                      {
++                              temp = items[len-1];
++                              items[len-1] = NULL;
++                              parsed_name = g_strjoinv("_",items);
++                              items[len-1] = temp;
++                      }
++
++                      pk_debug("type is %s, group is %s, parsed_name is %s",items[len-2],items[len-1],parsed_name);
++
++                      repo = (const gchar *)g_hash_table_lookup(releases,parsed_name);
++                      if (repo == NULL)
++                      {
++                              pk_debug("Can't find repo for %s, marking as \"unknown\"",parsed_name);
++                              repo = g_strdup("unknown");
++                              //g_assert(0);
++                      }
++                      else
++                              pk_debug("repo for %s is %s",parsed_name,repo);
++                      g_free(parsed_name);
++
++                      fullname = g_build_filename(sdir,fname,NULL);
++                      pk_debug("loading %s",fullname);
++                      if (g_file_get_contents(fullname,&contents,NULL,NULL) == FALSE)
++                      {
++                              pk_backend_error_code(backend, PK_ERROR_ENUM_INTERNAL_ERROR, "error loading %s",fullname);
++                              goto search_task_cleanup;
++                      }
++                      /*else
++                              pk_debug("loaded");*/
++
++                      res = sqlite3_bind_text(package,FIELD_REPO,repo,-1,SQLITE_TRANSIENT);
++                      if (res!=SQLITE_OK)
++                              pk_error("sqlite error during repo bind: %s", sqlite3_errmsg(db));
++                      /*else
++                              pk_debug("repo bind ok");*/
++
++                      res = sqlite3_exec(db,"begin",NULL,NULL,NULL);
++                      g_assert(res == SQLITE_OK);
++
++                      begin = contents;
++
++                      while (true)
++                      {
++                              next = strstr(begin,"\n");
++                              if (next!=NULL)
++                              {
++                                      next[0] = '\0';
++                                      next++;
++                              }
++
++                              if (begin[0]=='\0')
++                              {
++                                      if (haspk)
++                                      {
++                                              if (description!=NULL)
++                                              {
++                                                      res=sqlite3_bind_text(package,FIELD_LONG,description,-1,SQLITE_TRANSIENT);
++                                                      if (res!=SQLITE_OK)
++                                                              pk_error("sqlite error during description bind: %s", sqlite3_errmsg(db));
++                                                      g_free(description);
++                                                      description = NULL;
++                                              }
++                                              res = sqlite3_step(package);
++                                              if (res!=SQLITE_DONE)
++                                                      pk_error("sqlite error during step: %s", sqlite3_errmsg(db));
++                                              sqlite3_reset(package);
++                                              //pk_debug("added package");
++                                              haspk = FALSE;
++                                      }
++                                      //g_assert(0);
++                              }
++                              else if (begin[0]==' ')
++                              {
++                                      if (description == NULL)
++                                              description = g_strdup(&begin[1]);
++                                      else
++                                      {
++                                              gchar *oldval = description;
++                                              description = g_strconcat(oldval, "\n",&begin[1],NULL);
++                                              g_free(oldval);
++                                      }
++                              }
++                              else
++                              {
++                                      gchar *colon = strchr(begin,':');
++                                      g_assert(colon!=NULL);
++                                      colon[0] = '\0';
++                                      colon+=2;
++                                      /*if (strlen(colon)>3000)
++                                              pk_error("strlen(colon) = %d\ncolon = %s",strlen(colon),colon);*/
++                                      //pk_debug("entry = '%s','%s'",begin,colon);
++                                      if (begin[0] == 'P' && g_strcasecmp("Package",begin)==0)
++                                      {
++                                              res=sqlite3_bind_text(package,FIELD_PKG,colon,-1,SQLITE_STATIC);
++                                              haspk = TRUE;
++                                              count++;
++                                              if (count%1000==0)
++                                                      pk_debug("Package %ld (%s)",count,colon);
++                                      }
++                                      else if (begin[0] == 'V' && g_strcasecmp("Version",begin)==0)
++                                              res=sqlite3_bind_text(package,FIELD_VER,colon,-1,SQLITE_STATIC);
++                                      else if (begin[0] == 'D' && g_strcasecmp("Depends",begin)==0)
++                                              res=sqlite3_bind_text(package,FIELD_DEPS,colon,-1,SQLITE_STATIC);
++                                      else if (begin[0] == 'A' && g_strcasecmp("Architecture",begin)==0)
++                                              res=sqlite3_bind_text(package,FIELD_ARCH,colon,-1,SQLITE_STATIC);
++                                      else if (begin[0] == 'D' && g_strcasecmp("Description",begin)==0)
++                                              res=sqlite3_bind_text(package,FIELD_SHORT,colon,-1,SQLITE_STATIC);
++                                      if (res!=SQLITE_OK)
++                                              pk_error("sqlite error during %s bind: %s", begin, sqlite3_errmsg(db));
++                              }
++                              if (next == NULL)
++                                      break;
++                              begin = next;
++                      }
++                      res = sqlite3_exec(db,"commit",NULL,NULL,NULL);
++                      if (res!=SQLITE_OK)
++                              pk_error("sqlite error during commit: %s", sqlite3_errmsg(db));
++                      res = sqlite3_clear_bindings(package);
++                      if (res!=SQLITE_OK)
++                              pk_error("sqlite error during clear: %s", sqlite3_errmsg(db));
++                      g_free(contents);
++                      contents = NULL;
++              }
++      }
++      sqlite3_finalize(package);
++
++search_task_cleanup:
++      g_dir_close(dir);
++      g_free(sdir);
++      g_free(contents);
++}
++
+diff --git a/backends/apt.deprecated/pk-apt-build-db.h b/backends/apt.deprecated/pk-apt-build-db.h
+new file mode 100644
+index 0000000..bb786a9
+--- /dev/null
++++ b/backends/apt.deprecated/pk-apt-build-db.h
+@@ -0,0 +1,30 @@
++#ifndef PK_APT_BUILD_DB
++#define PK_APT_BUILD_DB
++
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
++ *
++ * Copyright (C) 2007 Tom Parker <palfrey@tevp.net>
++ *
++ * Licensed under the GNU General Public License Version 2
++ *
++ * 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 2 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, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++#include <sqlite3.h>
++#include <pk-backend.h>
++
++void apt_build_db(PkBackend * backend, sqlite3 *db);
++
++#endif
+diff --git a/backends/apt.deprecated/pk-apt-search-plain.c b/backends/apt.deprecated/pk-apt-search-plain.c
+new file mode 100644
+index 0000000..5e5b4e5
+--- /dev/null
++++ b/backends/apt.deprecated/pk-apt-search-plain.c
+@@ -0,0 +1,106 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
++ *
++ * Copyright (C) 2007 Ali Sabil <ali.sabil@gmail.com>
++ *
++ * Licensed under the GNU General Public License Version 2
++ *
++ * 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 2 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, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++#include <gmodule.h>
++#include <glib.h>
++#include <string.h>
++#include <pk-backend.h>
++#include <pk-backend-spawn.h>
++
++extern PkBackendSpawn *spawn;
++
++/**
++ * backend_get_groups:
++ */
++static PkGroupEnum
++backend_get_groups (PkBackend *backend)
++{
++      return (PK_GROUP_ENUM_ACCESSORIES |
++              PK_GROUP_ENUM_GAMES |
++              PK_GROUP_ENUM_GRAPHICS |
++              PK_GROUP_ENUM_INTERNET |
++              PK_GROUP_ENUM_OFFICE |
++              PK_GROUP_ENUM_OTHER |
++              PK_GROUP_ENUM_PROGRAMMING |
++              PK_GROUP_ENUM_MULTIMEDIA |
++              PK_GROUP_ENUM_SYSTEM);
++}
++
++/**
++ * backend_get_filters:
++ */
++static PkFilterEnum
++backend_get_filters (PkBackend *backend)
++{
++      return (PK_FILTER_ENUM_GUI |
++              PK_FILTER_ENUM_INSTALLED |
++              PK_FILTER_ENUM_DEVELOPMENT);
++}
++
++/**
++ * backend_get_details:
++ */
++
++void
++backend_get_details (PkBackend *backend, const gchar *package_id)
++{
++      pk_backend_spawn_helper (spawn, "get-details.py", package_id, NULL);
++}
++
++/**
++ * backend_search_details:
++ */
++
++void
++backend_search_details (PkBackend *backend, PkFilterEnum filters, const gchar *search)
++{
++      gchar *filters_text;
++      filters_text = pk_filter_enums_to_text (filters);
++      pk_backend_spawn_helper (spawn, "search-details.py", filters_texts_text, search, NULL);
++      g_free (filters_text);
++}
++
++/**
++ * backend_search_name:
++ */
++void
++backend_search_name (PkBackend *backend, PkFilterEnum filters, const gchar *search)
++{
++      gchar *filters_text;
++      filters_text = pk_filter_enums_to_text (filters);
++      pk_backend_spawn_helper (spawn, "search-name.py", filters_text, search, NULL);
++      g_free (filters_text);
++}
++
++/**
++ * backend_search_group:
++ */
++void
++backend_search_group (PkBackend *backend, PkFilterEnum filters, const gchar *search)
++{
++      gchar *filters_text;
++      pk_backend_spawn_helper (spawn, "search-group.py", filters_text, search, NULL);
++      g_free (filters_text);
++}
++
++/* don't need to do any setup/finalize in the plain search mode */
++void backend_init_search(PkBackend *backend) {}
++void backend_finish_search(PkBackend *backend) {}
+diff --git a/backends/apt.deprecated/pk-apt-search-sqlite.cpp b/backends/apt.deprecated/pk-apt-search-sqlite.cpp
+new file mode 100644
+index 0000000..98bdc7f
+--- /dev/null
++++ b/backends/apt.deprecated/pk-apt-search-sqlite.cpp
+@@ -0,0 +1,135 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
++ *
++ * Copyright (C) 2007 Ali Sabil <ali.sabil@gmail.com>
++ *
++ * Licensed under the GNU General Public License Version 2
++ *
++ * 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 2 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, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++#include <gmodule.h>
++#include <glib.h>
++#include <string.h>
++#include <pk-backend.h>
++#include <pk-backend-spawn.h>
++#include "pk-sqlite-pkg-cache.h"
++#include <apt-pkg/configuration.h>
++#include <apt-pkg/init.h>
++#include "pk-apt-build-db.h"
++
++static PkBackendSpawn *spawn;
++
++/**
++ * backend_get_groups:
++ */
++extern "C" PkGroupEnum
++backend_get_groups (PkBackend *backend)
++{
++      return (PK_GROUP_ENUM_ACCESSORIES |
++              PK_GROUP_ENUM_GAMES |
++              PK_GROUP_ENUM_GRAPHICS |
++              PK_GROUP_ENUM_INTERNET |
++              PK_GROUP_ENUM_OFFICE |
++              PK_GROUP_ENUM_OTHER |
++              PK_GROUP_ENUM_PROGRAMMING |
++              PK_GROUP_ENUM_MULTIMEDIA |
++              PK_GROUP_ENUM_SYSTEM);
++}
++
++/**
++ * backend_get_filters:
++ */
++extern "C" PkFilterEnum
++backend_get_filters (PkBackend *backend)
++{
++      return (PK_FILTER_ENUM_GUI |
++              PK_FILTER_ENUM_INSTALLED |
++              PK_FILTER_ENUM_DEVELOPMENT);
++}
++
++/**
++ * backend_get_details:
++ */
++
++extern "C" void
++backend_get_details (PkBackend *backend, const gchar *package_id)
++{
++      sqlite_get_details(backend,package_id);
++}
++
++/**
++ * backend_search_details:
++ */
++
++extern "C" void
++backend_search_details (PkBackend *backend, const gchar *filter, const gchar *search)
++{
++      sqlite_search_details(backend,filter,search);
++}
++
++/**
++ * backend_search_name:
++ */
++extern "C" void
++backend_search_name (PkBackend *backend, const gchar *filter, const gchar *search)
++{
++      sqlite_search_name(backend,filter,search);
++}
++
++/**
++ * backend_search_group:
++ */
++extern "C" void
++backend_search_group (PkBackend *backend, const gchar *filter, const gchar *search)
++{
++      pk_backend_set_allow_cancel (backend, TRUE);
++      pk_backend_spawn_helper (spawn, "search-group.py", filter, search, NULL);
++}
++
++static gboolean inited = FALSE;
++
++#define APT_DB PK_DB_DIR "/apt.db"
++
++extern "C" void backend_init_search(PkBackend *backend)
++{
++      if (!inited)
++      {
++              gchar *apt_fname = NULL;
++              if (pkgInitConfig(*_config) == false)
++                      pk_debug("pkginitconfig was false");
++              if (pkgInitSystem(*_config, _system) == false)
++                      pk_debug("pkginitsystem was false");
++
++              apt_fname = g_strconcat(
++                              _config->Find("Dir").c_str(),
++                              _config->Find("Dir::Cache").c_str(),
++                              _config->Find("Dir::Cache::pkgcache").c_str(),
++                              NULL);
++
++              //sqlite_set_installed_check(is_installed);
++              sqlite_init_cache(backend, APT_DB, apt_fname, apt_build_db);
++              g_free(apt_fname);
++
++              spawn = pk_backend_spawn_new ();
++              pk_backend_spawn_set_name (spawn, "apt-sqlite");
++
++              inited = TRUE;
++      }
++}
++
++extern "C" void backend_finish_search(PkBackend *backend)
++{
++      sqlite_finish_cache(backend);
++}
+diff --git a/backends/apt.deprecated/pk-apt-search.h b/backends/apt.deprecated/pk-apt-search.h
+new file mode 100644
+index 0000000..e36e89f
+--- /dev/null
++++ b/backends/apt.deprecated/pk-apt-search.h
+@@ -0,0 +1,36 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
++ *
++ * Copyright (C) 2007 Tom Parker <palfrey@tevp.net>
++ *
++ * Licensed under the GNU General Public License Version 2
++ *
++ * 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 2 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, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++#ifndef __PK_APT_SEARCH_H
++#define __PK_APT_SEARCH_H
++
++#include <glib.h>
++#include <pk-backend.h>
++
++void backend_init_search(PkBackend *backend);
++void backend_finish_search(PkBackend *backend);
++
++void backend_get_details (PkBackend *backend, const gchar *package_id);
++void backend_search_details (PkBackend *backend, const gchar *filter, const gchar *search);
++void backend_search_name (PkBackend *backend, const gchar *filter, const gchar *search);
++void backend_search_group (PkBackend *backend, const gchar *filter, const gchar *search);
++
++#endif
+diff --git a/backends/apt.deprecated/pk-backend-apt.c b/backends/apt.deprecated/pk-backend-apt.c
+new file mode 100644
+index 0000000..f59cd88
+--- /dev/null
++++ b/backends/apt.deprecated/pk-backend-apt.c
+@@ -0,0 +1,268 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
++ *
++ * Copyright (C) 2007 Ali Sabil <ali.sabil@gmail.com>
++ * Copyright (C) 2007 Tom Parker <palfrey@tevp.net>
++ *
++ * Licensed under the GNU General Public License Version 2
++ *
++ * 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 2 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, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++#include <gmodule.h>
++#include <glib.h>
++#include <string.h>
++#include <pk-backend.h>
++#include <pk-backend-spawn.h>
++#include <pk-package-ids.h>
++#include "pk-apt-search.h"
++#include "config.h"
++
++PkBackendSpawn *spawn;
++
++/**
++ * backend_initialize:
++ * This should only be run once per backend load, i.e. not every transaction
++ */
++static void
++backend_initialize (PkBackend *backend)
++{
++      pk_debug ("FILTER: initialize");
++      spawn = pk_backend_spawn_new ();
++      pk_backend_spawn_set_name (spawn, "apt");
++      backend_init_search (backend);
++}
++
++/**
++ * backend_destroy:
++ * This should only be run once per backend load, i.e. not every transaction
++ */
++static void
++backend_destroy (PkBackend *backend)
++{
++      pk_debug ("FILTER: destroy");
++      backend_finish_search (backend);
++      g_object_unref (spawn);
++}
++
++/**
++ * backend_get_groups:
++ */
++static PkGroupEnum
++backend_get_groups (PkBackend *backend)
++{
++      return (PK_GROUP_ENUM_ACCESSORIES |
++              PK_GROUP_ENUM_GAMES |
++              PK_GROUP_ENUM_GRAPHICS |
++              PK_GROUP_ENUM_INTERNET |
++              PK_GROUP_ENUM_OFFICE |
++              PK_GROUP_ENUM_OTHER |
++              PK_GROUP_ENUM_PROGRAMMING |
++              PK_GROUP_ENUM_MULTIMEDIA |
++              PK_GROUP_ENUM_SYSTEM);
++}
++
++/**
++ * backend_get_filters:
++ */
++static PkFilterEnum
++backend_get_filters (PkBackend *backend)
++{
++      return (PK_FILTER_ENUM_GUI |
++              PK_FILTER_ENUM_INSTALLED |
++              PK_FILTER_ENUM_DEVELOPMENT);
++}
++
++/**
++ * pk_backend_bool_to_text:
++ */
++static const gchar *
++pk_backend_bool_to_text (gboolean value)
++{
++      if (value == TRUE) {
++              return "yes";
++      }
++      return "no";
++}
++
++/**
++ * backend_get_depends:
++ */
++static void
++backend_get_depends (PkBackend *backend, PkFilterEnum filters, const gchar *package_id, gboolean recursive)
++{
++      gchar *filters_text;
++      filters_text = pk_filter_enums_to_text (filters);
++      pk_backend_spawn_helper (spawn, "get-depends.py", filters_text, package_id, pk_backend_bool_to_text (recursive), NULL);
++      g_free (filters_text);
++}
++
++/**
++ * backend_get_updates:
++ */
++static void
++backend_get_updates (PkBackend *backend, PkFilterEnum filters)
++{
++      gchar *filters_text;
++      filters_text = pk_filter_enums_to_text (filters);
++      pk_backend_spawn_helper (spawn, "get-updates.py", filters_text, NULL);
++      g_free (filters_text);
++}
++
++/**
++ * backend_get_update_detail:
++ */
++static void
++backend_get_update_detail (PkBackend *backend, const gchar *package_id)
++{
++      pk_backend_spawn_helper (spawn, "get-update-detail.py", package_id, NULL);
++}
++
++/**
++ * backend_install_packages:
++ */
++static void
++backend_install_packages (PkBackend *backend, gchar **package_ids)
++{
++      gchar *package_ids_temp;
++
++      /* check network state */
++      if (!pk_backend_is_online (backend)) {
++              pk_backend_error_code (backend, PK_ERROR_ENUM_NO_NETWORK, "Cannot install when offline");
++              pk_backend_finished (backend);
++              return;
++      }
++
++      /* send the complete list as stdin */
++      package_ids_temp = pk_package_ids_to_text (package_ids, "|");
++      pk_backend_spawn_helper (spawn, "install-packages.py", package_ids_temp, NULL);
++      g_free (package_ids_temp);
++}
++
++/**
++ * backend_refresh_cache:
++ */
++static void
++backend_refresh_cache (PkBackend *backend, gboolean force)
++{
++      /* check network state */
++      if (!pk_backend_is_online (backend)) {
++              pk_backend_error_code (backend, PK_ERROR_ENUM_NO_NETWORK, "Cannot refresh cache whilst offline");
++              pk_backend_finished (backend);
++              return;
++      }
++
++      pk_backend_spawn_helper (spawn, "refresh-cache.py", NULL);
++}
++
++/**
++ * pk_backend_remove_packages:
++ * 
++static void
++backend_remove_packages (PkBackend *backend, gchar **package_ids, gboolean allow_deps, gboolean autoremove)
++{
++      gchar *package_ids_temp;
++      package_ids_temp = pk_package_ids_to_text (package_ids, "|");
++      pk_backend_spawn_helper (spawn, "remove-packages.py", pk_backend_bool_to_text (allow_deps), package_ids_temp, NULL);
++      g_free (package_ids_temp);
++} */
++
++/**
++ * pk_backend_update_packages:
++ */
++static void
++backend_update_packages (PkBackend *backend, gchar **package_ids)
++{
++      gchar *package_ids_temp;
++
++      /* check network state */
++      if (!pk_backend_is_online (backend)) {
++              pk_backend_error_code (backend, PK_ERROR_ENUM_NO_NETWORK, "Cannot install when offline");
++              pk_backend_finished (backend);
++              return;
++      }
++
++      /* send the complete list as stdin */
++      package_ids_temp = pk_package_ids_to_text (package_ids, "|");
++      pk_backend_spawn_helper (spawn, "update-packages.py", package_ids_temp, NULL);
++      g_free (package_ids_temp);
++}
++
++/**
++ * pk_backend_update_system:
++ */
++static void
++backend_update_system (PkBackend *backend)
++{
++      pk_backend_spawn_helper (spawn, "update-system.py", NULL);
++}
++
++/**
++ * pk_backend_resolve:
++ */
++static void
++backend_resolve (PkBackend *backend, PkFilterEnum filters, const gchar *package_id)
++{
++      gchar *filters_text;
++      filters_text = pk_filter_enums_to_text (filters);
++      pk_backend_spawn_helper (spawn, "resolve.py", filters_text, package_id, NULL);
++      g_free (filters_text);
++}
++
++/**
++ * pk_backend_get_repo_list:
++ */
++static void
++backend_get_repo_list (PkBackend *backend, PkFilterEnum filters)
++{
++      gchar *filters_text;
++      filters_text = pk_filter_enums_to_text (filters);
++      pk_backend_spawn_helper (spawn, "get-repo-list.py", filters_text, NULL);
++      g_free (filters_text);
++}
++
++PK_BACKEND_OPTIONS (
++      "Apt (with " APT_SEARCH " searching)",                          /* description */
++      "Ali Sabil <ali.sabil@gmail.com>; Tom Parker <palfrey@tevp.net>",       /* author */
++      backend_initialize,                     /* initalize */
++      backend_destroy,                        /* destroy */
++      backend_get_groups,                     /* get_groups */
++      backend_get_filters,                    /* get_filters */
++      NULL,                                   /* cancel */
++      backend_get_depends,                    /* get_depends */
++      backend_get_details,                    /* get_details */
++      NULL,                                   /* get_files */
++      NULL,                                   /* get_packages */
++      backend_get_repo_list,                  /* get_repo_list */
++      NULL,                                   /* get_requires */
++      backend_get_update_detail,              /* get_update_detail */
++      backend_get_updates,                    /* get_updates */
++      NULL,                                   /* install_files */
++      backend_install_packages,               /* install_packages */
++      NULL,                                   /* install_signature */
++      backend_refresh_cache,                  /* refresh_cache */
++      NULL,                                   /* remove_packages */
++      NULL,                                   /* repo_enable */
++      NULL,                                   /* repo_set_data */
++      backend_resolve,                        /* resolve */
++      NULL,                                   /* rollback */
++      backend_search_details,                 /* search_details */
++      NULL,                                   /* search_file */
++      backend_search_group,                   /* search_group */
++      backend_search_name,                    /* search_name */
++      NULL,                                   /* service_pack */
++      backend_update_package,                 /* update_package */
++      backend_update_system,                  /* update_system */
++      NULL                                    /* what_provides */
++);
+diff --git a/backends/apt.deprecated/pk-sqlite-pkg-cache.cpp b/backends/apt.deprecated/pk-sqlite-pkg-cache.cpp
+new file mode 100644
+index 0000000..1bf9a50
+--- /dev/null
++++ b/backends/apt.deprecated/pk-sqlite-pkg-cache.cpp
+@@ -0,0 +1,215 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
++ *
++ * Copyright (C) 2007 Tom Parker <palfrey@tevp.net>
++ *
++ * Licensed under the GNU General Public License Version 2
++ *
++ * 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 2 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, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++#include <glib.h>
++#include <glib/gstdio.h>
++#include "pk-sqlite-pkg-cache.h"
++
++static sqlite3 *db = NULL;
++static PkBackend *backend;
++static gboolean(*is_installed) (const PkPackageId *) = NULL;
++
++void sqlite_set_installed_check(gboolean(*func) (const PkPackageId *))
++{
++      is_installed = func;
++}
++
++void
++sqlite_init_cache(PkBackend *backend, const char* dbname, const char *compare_fname, void (*build_db)(PkBackend *, sqlite3 *))
++{
++      int ret;
++      struct stat st;
++      time_t db_age;
++
++      ret = sqlite3_open (dbname, &db);
++      g_assert(ret == SQLITE_OK);
++      g_assert(db!=NULL);
++      ret = sqlite3_exec(db,"PRAGMA synchronous = OFF",NULL,NULL,NULL);
++      g_assert(ret == SQLITE_OK);
++
++      g_stat(dbname, &st);
++      db_age = st.st_mtime;
++      g_stat(compare_fname, &st);
++      if (db_age>=st.st_mtime)
++      {
++              ret = sqlite3_exec(db, "select value from params where name = 'build_complete'", NULL, NULL, NULL);
++              if (ret != SQLITE_ERROR)
++                      return;
++              pk_debug("ages are %lu for db, and %lu for comparism",db_age,st.st_mtime);
++      }
++      ret = sqlite3_exec(db,"drop table packages",NULL,NULL,NULL); // wipe it!
++      //g_assert(ret == SQLITE_OK);
++      pk_debug("wiped db");
++      ret = sqlite3_exec(db,"create table packages (name text, version text, deps text, arch text, short_desc text, long_desc text, repo string, primary key(name,version,arch,repo))",NULL,NULL,NULL);
++      g_assert(ret == SQLITE_OK);
++
++      build_db(backend,db);
++
++      sqlite3_exec(db,"create table params (name text primary key, value integer)", NULL, NULL, NULL);
++      sqlite3_exec(db,"insert into params values ('build_complete',1)", NULL, NULL, NULL);
++}
++
++void sqlite_finish_cache(PkBackend *backend)
++{
++      sqlite3_close(db);
++}
++
++// sqlite_search_packages_thread
++static gboolean
++sqlite_search_packages_thread (PkBackend *backend)
++{
++      int res;
++      gchar *sel;
++      const gchar *search;
++
++      pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY);
++      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
++      type = pk_backend_get_uint (backend, "type");
++      search = pk_backend_get_string (backend, "search");
++
++      pk_debug("finding %s", search);
++
++      sqlite3_stmt *package = NULL;
++      g_strdelimit(search," ",'%');
++
++      if (type == SEARCH_NAME)
++              sel = g_strdup_printf("select name,version,arch,repo,short_desc from packages where name like '%%%s%%'",search);
++      else if (type == SEARCH_DETAILS)
++              sel = g_strdup_printf("select name,version,arch,repo,short_desc from packages where name like '%%%s%%' or short_desc like '%%%s%%' or long_desc like '%%%s%%'",search, search, search);
++      else
++      {
++              pk_backend_error_code(backend, PK_ERROR_ENUM_INTERNAL_ERROR, "Unknown search task type");
++              goto end_search_packages;
++      }
++
++      pk_debug("statement is '%s'",sel);
++      res = sqlite3_prepare_v2(db,sel, -1, &package, NULL);
++      g_free(sel);
++      if (res!=SQLITE_OK)
++              pk_error("sqlite error during select prepare: %s", sqlite3_errmsg(db));
++      res = sqlite3_step(package);
++      while (res == SQLITE_ROW)
++      {
++              PkPackageId *pid = pk_package_id_new_from_list((const gchar*)sqlite3_column_text(package,0),
++                              (const gchar*)sqlite3_column_text(package,1),
++                              (const gchar*)sqlite3_column_text(package,2),
++                              (const gchar*)sqlite3_column_text(package,3));
++
++              gchar *cpid = pk_package_id_to_string(pid);
++              PkInfoEnum pie = PK_INFO_ENUM_UNKNOWN;
++
++              if (is_installed != NULL)
++                      pie = is_installed(pid)?PK_INFO_ENUM_INSTALLED:PK_INFO_ENUM_AVAILABLE;
++
++              pk_backend_package(backend, pie, cpid, (const gchar*)sqlite3_column_text(package,4));
++
++              g_free(cpid);
++              pk_package_id_free(pid);
++
++              if (res==SQLITE_ROW)
++                      res = sqlite3_step(package);
++      }
++      if (res!=SQLITE_DONE)
++      {
++              pk_debug("sqlite error during step (%d): %s", res, sqlite3_errmsg(db));
++              g_assert(0);
++      }
++
++end_search_packages:
++      pk_backend_finished (backend);
++      return TRUE;
++}
++
++/**
++ * sqlite_search_details:
++ */
++void
++sqlite_search_details (PkBackend *backend, const gchar *filter, const gchar *search)
++{
++      pk_backend_set_uint (backend, "type", SEARCH_DETAILS);
++      pk_backend_thread_create (backend, sqlite_search_packages_thread);
++}
++
++/**
++ * sqlite_search_name:
++ */
++void
++sqlite_search_name (PkBackend *backend, const gchar *filter, const gchar *search)
++{
++      pk_backend_set_uint (backend, "type", SEARCH_NAME);
++      pk_backend_thread_create (backend, sqlite_search_packages_thread);
++}
++
++// sqlite_get_details_thread
++static gboolean
++sqlite_get_details_thread (PkBackend *backend)
++{
++      PkPackageId *pi;
++      const gchar *package_id;
++      int res;
++
++      package_id = pk_backend_get_string (backend, "package_id");
++      pi = pk_package_id_new_from_string(package_id);
++      if (pi == NULL)
++      {
++              pk_backend_error_code(backend, PK_ERROR_ENUM_PACKAGE_ID_INVALID, "invalid package id");
++              pk_backend_finished(backend);
++              return;
++      }
++
++      pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY);
++      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
++
++      pk_debug("finding %s", pi->name);
++
++      sqlite3_stmt *package = NULL;
++      gchar *sel = g_strdup_printf("select long_desc from packages where name = '%s' and version = '%s' and repo = '%s'",pi->name,pi->version,pi->data);
++      pk_debug("statement is '%s'",sel);
++      res = sqlite3_prepare_v2(db,sel, -1, &package, NULL);
++      g_free(sel);
++      if (res!=SQLITE_OK)
++              pk_error("sqlite error during select prepare: %s", sqlite3_errmsg(db));
++      res = sqlite3_step(package);
++      pk_backend_details(backend,pi->name, "unknown", PK_GROUP_ENUM_OTHER,(const gchar*)sqlite3_column_text(package,0),"",0);
++      res = sqlite3_step(package);
++      if (res==SQLITE_ROW)
++              pk_error("multiple matches for that package!");
++      if (res!=SQLITE_DONE)
++      {
++              pk_debug("sqlite error during step (%d): %s", res, sqlite3_errmsg(db));
++              g_assert(0);
++      }
++
++      g_free(dt);
++
++      return TRUE;
++}
++
++/**
++ * sqlite_get_details:
++ */
++extern "C++" void
++sqlite_get_details (PkBackend *backend, const gchar *package_id)
++{
++      pk_backend_thread_create (backend, sqlite_get_details_thread);
++      return;
++}
++
+diff --git a/backends/apt.deprecated/pk-sqlite-pkg-cache.h b/backends/apt.deprecated/pk-sqlite-pkg-cache.h
+new file mode 100644
+index 0000000..68fad42
+--- /dev/null
++++ b/backends/apt.deprecated/pk-sqlite-pkg-cache.h
+@@ -0,0 +1,42 @@
++#ifndef SQLITE_PKT_CACHE
++#define SQLITE_PKT_CACHE
++
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
++ *
++ * Copyright (C) 2007 Tom Parker <palfrey@tevp.net>
++ *
++ * Licensed under the GNU General Public License Version 2
++ *
++ * 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 2 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, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++typedef enum {
++      SEARCH_NAME = 1,
++      SEARCH_DETAILS,
++      SEARCH_FILE
++} SearchDepth;
++
++#include <pk-backend.h>
++#include <sqlite3.h>
++
++void sqlite_init_cache(PkBackend *backend, const char* dbname, const char* compare_fname, void (*build_db)(PkBackend *, sqlite3 *db));
++void sqlite_finish_cache(PkBackend *backend);
++
++void sqlite_search_details (PkBackend *backend, const gchar *filter, const gchar *search);
++void sqlite_search_name (PkBackend *backend, const gchar *filter, const gchar *search);
++void backend_search_common(PkBackend * backend, const gchar * filter, const gchar * search, SearchDepth which, PkBackendThreadFunc func);
++void sqlite_get_details (PkBackend *backend, const gchar *package_id);
++
++#endif
+diff --git a/backends/apt/HACKING b/backends/apt/HACKING
+new file mode 100644
+index 0000000..2b99c5d
+--- /dev/null
++++ b/backends/apt/HACKING
+@@ -0,0 +1,5 @@
++The backend can be tested by running it as root from the source code
++repository. Make sure to kill packagekitd before to force a reintializing
++of the cache:
++
++  killall packagekitd; python aptDBUSBackend.py 
+diff --git a/backends/apt/Makefile.am b/backends/apt/Makefile.am
+index 07b4131..e315ba9 100644
+--- a/backends/apt/Makefile.am
++++ b/backends/apt/Makefile.am
+@@ -1,30 +1,25 @@
+-NULL =
++NULL = 
+-SUBDIRS = helpers
+ plugindir = $(PK_PLUGIN_DIR)
+ plugin_LTLIBRARIES = libpk_backend_apt.la
+-
++libpk_backend_apt_la_SOURCES = pk-backend-apt.c
+ libpk_backend_apt_la_LIBADD = $(PK_PLUGIN_LIBS)
+-libpk_backend_apt_la_LDFLAGS = -module -avoid-version $(APT_LIBS)
+-libpk_backend_apt_la_CFLAGS = $(PK_PLUGIN_CFLAGS) $(APT_CFLAGS)
+-libpk_backend_apt_la_CXXFLAGS = $(PK_PLUGIN_CFLAGS) $(APT_CFLAGS) -DPK_DB_DIR=\""$(PK_DB_DIR)"\"
++libpk_backend_apt_la_LDFLAGS = -module -avoid-version
++libpk_backend_apt_la_CFLAGS = $(PK_PLUGIN_CFLAGS)
++
++dbusinstancedir = $(LIBEXECDIR)
++dbusinstance_DATA =                                     \
++        aptDBUSBackend.py                               \
++        $(NULL)
++
++EXTRA_DIST =                                            \
++        $(dbusinstance_DATA)                            \
++        $(NULL)
+-libpk_backend_apt_la_SOURCES =                                \
+-      pk-backend-apt.c                                \
+-      pk-apt-search.h                                 \
+-      $(NULL)
++install-data-hook:
++      chmod a+rx $(DESTDIR)$(libexecdir)/*.py
+-if APT_SEARCH_PLAIN
+-libpk_backend_apt_la_SOURCES +=                               \
+-      pk-apt-search-plain.c                           \
+-      $(NULL)
+-endif
++clean-local :
++      rm -f *~
++      rm -f *.pyc
+-if APT_SEARCH_SQLITE
+-libpk_backend_apt_la_SOURCES +=                               \
+-      pk-sqlite-pkg-cache.h                           \
+-      pk-sqlite-pkg-cache.cpp                         \
+-      pk-apt-build-db.cpp                             \
+-      pk-apt-search-sqlite.cpp                        \
+-      $(NULL)
+-endif
+diff --git a/backends/apt/README b/backends/apt/README
+new file mode 100644
+index 0000000..0a3da6e
+--- /dev/null
++++ b/backends/apt/README
+@@ -0,0 +1,23 @@
++The name of this backend is apt2.
++
++It supports apt which is mainly used by Debian and its derivates. In contrast to
++the backend called apt this one uses DBus for the communication with the 
++packagekit daemon. This allows to perform actions without having to reopen
++the cache for each one.
++
++To provide a tremendously fast search function a Xapian database is used.
++It is provided by Enrico Zini's apt-xapian-index. Debtags will be used to 
++enhance the quality of the search results further.
++
++A list of implemented functions are listed in the PackageKit FAQ:
++
++http://www.packagekit.org/pk-faq.html
++
++You can find packages for Ubuntu here:
++
++https://www.launchpad.net/~packagekit/+ppa
++
++Packages for Debian Unstable will be provided soon.
++
++Feel free to send comments or bug reports to the PackageKit mailing list
++or to the author.
+diff --git a/backends/apt/TODO b/backends/apt/TODO
+new file mode 100644
+index 0000000..bee2f3d
+--- /dev/null
++++ b/backends/apt/TODO
+@@ -0,0 +1,70 @@
++ISSUES:
++
++ * Support delayed or hidden debconf questions
++
++Unresolved issues can be discussed at the following wiki page:
++http://wiki.debian.org/PackageKit
++
++
++TODO:
++
++ * Implement all open backend methods. A list of implemented backend methods 
++   can be found in PackageKit FAQ or in pk-backend-apt2.c.
++
++ * Blacklist packages requiring input on the terminal and try to change
++   the Debian policy in the long run. Way of automation?
++ 
++ * Allow to inject alternative apt.package.Package classes into the
++   cache to support PackageKit and distribution specific needs
++   (e.g. when is a package called free or supported)
++
++ * Allow to reinject debtags into the search results to get 
++   similar software which not matches on the search terms
++
++ * Index file list and add properties for package name and section to
++   the xapian database to also make use of it in search group and 
++   search name (do we want this?)
++
++ * Map Debian/Ubuntu sections to PackageKit groups:
++    - admin : System Administration           => admin-tools
++    - base : Base System                      => system
++    - comm : Communication                    => communication
++    - devel : Development                     => programming
++    - doc : Documentation                     => ???
++    - editors : Editors                               => accessoires
++    - electronics : Electronics                       => other
++    - embedded : Embedded Devices             => system
++    - games : Games and Amusement             => games
++    - gnome : GNOME Desktop Environment               => desktop-gnome
++    - graphics : Graphics                     => graphics
++    - hamradio : Amateur Radio                        => communication
++    - interpreters : Interpreted Computer L.  => programming
++    - kde : KDE Desktop Environment           => desktop-kde
++    - libdevel : Libraries - Development      => programming
++    - libs : Libraries                                => system
++    - mail : Email                            => internet
++    - math : Mathematics                      => ??? science/education
++    - misc : Miscellaneous - Text Based               => other
++    - net : Networkinga                               => network
++    - news : Newsgroup                                => internet
++    - oldlibs : Libraries - Old                       => legacy
++    - otherosfs : Cross Platform              => system
++    - perl : Perl Programming Language                => programming
++    - python : Python Programming Language    => programming
++    - science : Science                               => ??? science/education
++    - shells : Shells                         => system
++    - sound : Multimedia                      => multimedia
++    - tex : TeX Authoring                     => publishing
++    - text : Word Processing                  => publishing
++    - utils : Utilities                               => accessoires
++    - web : World Wide Web                    => internet
++    - x11 : Miscellaneous  - Graphical                => desktop-other
++    - unknown : Unknown                               => unknown
++    - alien : Converted From RPM by Alien"    => unknown
++    - translations                            => localization
++  The following could not be maped: science, documentation, electronics
++  Are there any derivates with additional sections?
++
++ * Fix the dbus policy. Should we require at_console for searching?
++ 
++DONE:
+diff --git a/backends/apt/aptDBUSBackend.py b/backends/apt/aptDBUSBackend.py
+new file mode 100755
+index 0000000..22eb714
+--- /dev/null
++++ b/backends/apt/aptDBUSBackend.py
+@@ -0,0 +1,679 @@
++#!/usr/bin/env python
++# -*- coding: utf-8 -*-
++"""
++Provides an apt backend to PackageKit
++
++Copyright (C) 2007 Ali Sabil <ali.sabil@gmail.com>
++Copyright (C) 2007 Tom Parker <palfrey@tevp.net>
++Copyright (C) 2008 Sebastian Heinlein <glatzor@ubuntu.com>
++
++Licensed under the GNU General Public License Version 2
++
++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 2 of the License, or
++(at your option) any later version.
++"""
++
++__author__  = "Sebastian Heinlein <devel@glatzor.de>"
++__state__   = "experimental"
++
++import os
++import pty
++import re
++import signal
++import time
++import threading
++import warnings
++
++import apt
++import apt_pkg
++import dbus
++import dbus.glib
++import dbus.service
++import dbus.mainloop.glib
++import gobject
++
++from packagekit.daemonBackend import PACKAGEKIT_DBUS_INTERFACE, PACKAGEKIT_DBUS_PATH, PackageKitBaseBackend, PackagekitProgress, pklog, threaded, async
++from packagekit.enums import *
++
++warnings.filterwarnings(action='ignore', category=FutureWarning)
++
++PACKAGEKIT_DBUS_SERVICE = 'org.freedesktop.PackageKitAptBackend'
++
++XAPIANDBPATH = os.environ.get("AXI_DB_PATH", "/var/lib/apt-xapian-index")
++XAPIANDB = XAPIANDBPATH + "/index"
++XAPIANDBVALUES = XAPIANDBPATH + "/values"
++
++# Required for daemon mode
++os.putenv("PATH",
++          "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin")
++# Avoid questions from the maintainer scripts as far as possible
++os.putenv("DEBIAN_FRONTEND", "noninteractive")
++os.putenv("APT_LISTCHANGES_FRONTEND", "none")
++
++# Setup threading support
++gobject.threads_init()
++dbus.glib.threads_init()
++
++class PackageKitOpProgress(apt.progress.OpProgress):
++    '''
++    Handle the cache opening process
++    '''
++    def __init__(self, backend, prange=(0,100), progress=True):
++        self._backend = backend
++        apt.progress.OpProgress.__init__(self)
++        self.steps = []
++        for v in [0.12, 0.25, 0.50, 0.75, 1.00]:
++            s = prange[0] + (prange[1] - prange[0]) * v
++            self.steps.append(s)
++        self.pstart = float(prange[0])
++        self.pend = self.steps.pop(0)
++        self.pprev = None
++        self.show_progress = progress
++
++    # OpProgress callbacks
++    def update(self, percent):
++        progress = int(self.pstart + percent / 100 * (self.pend - self.pstart))
++        if self.show_progress == True and self.pprev < progress:
++            self._backend.PercentageChanged(progress)
++            self.pprev = progress
++
++    def done(self):
++        self.pstart = self.pend
++        try:
++            self.pend = self.steps.pop(0)
++        except:
++            pklog.warning("An additional step to open the cache is required")
++
++class PackageKitFetchProgress(apt.progress.FetchProgress):
++    '''
++    Handle the package download process
++    '''
++    def __init__(self, backend, prange=(0,100)):
++        self._backend = backend
++        apt.progress.FetchProgress.__init__(self)
++        self.pstart = prange[0]
++        self.pend = prange[1]
++        self.pprev = None
++
++    # FetchProgress callbacks
++    def pulse(self):
++        if self._backend._canceled.isSet():
++            return False
++        percent = ((self.currentBytes + self.currentItems)*100.0)/float(self.totalBytes+self.totalItems)
++        progress = int(self.pstart + percent/100 * (self.pend - self.pstart))
++        if self.pprev < progress:
++            self._backend.PercentageChanged(progress)
++            self.pprev = progress
++        apt.progress.FetchProgress.pulse(self)
++        return True
++
++    def start(self):
++        self._backend.StatusChanged(STATUS_DOWNLOAD)
++        self._backend.AllowCancel(True)
++
++    def stop(self):
++        self._backend.PercentageChanged(self.pend)
++        self._backend.AllowCancel(False)
++
++    def mediaChange(self, medium, drive):
++        #FIXME: use the Message method to notify the user
++        self._backend.error(ERROR_UNKNOWN,
++                            "Medium change needed")
++
++class PackageKitInstallProgress(apt.progress.InstallProgress):
++    '''
++    Handle the installation and removal process. Bits taken from
++    DistUpgradeViewNonInteractive.
++    '''
++    def __init__(self, backend, prange=(0,100)):
++        apt.progress.InstallProgress.__init__(self)
++        self._backend = backend
++        self.timeout = 900
++        self.pstart = prange[0]
++        self.pend = prange[1]
++        self.pprev = None
++
++    def statusChange(self, pkg, percent, status):
++        progress = self.pstart + percent/100 * (self.pend - self.pstart)
++        if self.pprev < progress:
++            self._backend.PercentageChanged(int(progress))
++            self.pprev = progress
++        pklog.debug("PM status: %s" % status)
++
++    def startUpdate(self):
++        self._backend.StatusChanged(STATUS_INSTALL)
++        self.last_activity = time.time()
++
++    def updateInterface(self):
++        pklog.debug("Updating interface")
++        apt.progress.InstallProgress.updateInterface(self)
++
++    def conffile(self, current, new):
++        pklog.critical("Config file prompt: '%s'" % current)
++
++def sigquit(signum, frame):
++    pklog.error("Was killed")
++    sys.exit(1)
++
++class PackageKitAptBackend(PackageKitBaseBackend):
++    '''
++    PackageKit backend for apt
++    '''
++    def __init__(self, bus_name, dbus_path):
++        pklog.info("Initializing APT backend")
++        signal.signal(signal.SIGQUIT, sigquit)
++        self._cache = None
++        self._canceled = threading.Event()
++        self._canceled.clear()
++        self._lock = threading.Lock()
++        # Check for xapian support
++        self._use_xapian = False
++        try:
++            import xapian
++        except ImportError:
++            pass
++        else:
++            if os.access(XAPIANDB, os.R_OK):
++                self._use_xapian = True
++        PackageKitBaseBackend.__init__(self, bus_name, dbus_path)
++
++    # Methods ( client -> engine -> backend )
++
++    def doInit(self):
++        pklog.info("Initializing cache")
++        self.StatusChanged(STATUS_SETUP)
++        self.AllowCancel(False)
++        self.NoPercentageUpdates()
++        self._open_cache(progress=False)
++
++    def doExit(self):
++        pass
++
++    @threaded
++    def doCancel(self):
++        pklog.info("Canceling current action")
++        self.StatusChanged(STATUS_CANCEL)
++        self._canceled.set()
++        self._canceled.wait()
++
++    @threaded
++    def doSearchName(self, filters, search):
++        '''
++        Implement the apt2-search-name functionality
++        '''
++        pklog.info("Searching for package name: %s" % search)
++        self.StatusChanged(STATUS_QUERY)
++        self.NoPercentageUpdates()
++        self._check_init(progress=False)
++        self.AllowCancel(True)
++
++        for pkg in self._cache:
++            if self._canceled.isSet():
++                self.ErrorCode(ERROR_TRANSACTION_CANCELLED,
++                               "The search was canceled")
++                self.Finished(EXIT_KILL)
++                self._canceled.clear()
++                return
++            elif search in pkg.name and self._is_package_visible(pkg, filters):
++                self._emit_package(pkg)
++        self.Finished(EXIT_SUCCESS)
++
++    @threaded
++    def doSearchDetails(self, filters, search):
++        '''
++        Implement the apt2-search-details functionality
++        '''
++        pklog.info("Searching for package name: %s" % search)
++        self.StatusChanged(STATUS_QUERY)
++        self.NoPercentageUpdates()
++        self._check_init(progress=False)
++        self.AllowCancel(True)
++        results = []
++
++        if self._use_xapian == True:
++            search_flags = (xapian.QueryParser.FLAG_BOOLEAN |
++                            xapian.QueryParser.FLAG_PHRASE |
++                            xapian.QueryParser.FLAG_LOVEHATE |
++                            xapian.QueryParser.FLAG_BOOLEAN_ANY_CASE)
++            pklog.debug("Performing xapian db based search")
++            db = xapian.Database(XAPIANDB)
++            parser = xapian.QueryParser()
++            query = parser.parse_query(unicode(search),
++                                       search_flags)
++            enquire = xapian.Enquire(db)
++            enquire.set_query(query)
++            matches = enquire.get_mset(0, 1000)
++            for r in  map(lambda m: m[xapian.MSET_DOCUMENT].get_data(),
++                          enquire.get_mset(0,1000)):
++                if self._cache.has_key(r):
++                    results.append(self._cache[r])
++        else:
++            pklog.debug("Performing apt cache based search")
++            for p in self._cache._dict.values():
++                if self._check_canceled("Search was canceled"): return
++                needle = search.strip().lower()
++                haystack = p.description.lower()
++                if p.name.find(needle) >= 0 or haystack.find(needle) >= 0:
++                    results.append(p)
++
++        for r in results:
++            if self._check_canceled("Search was canceled"): return
++            if self._is_package_visible(r, filters) == True:
++                self._emit_package(r)
++
++        self.Finished(EXIT_SUCCESS)
++
++    @threaded
++    @async
++    def doGetUpdates(self, filters):
++        '''
++        Implement the {backend}-get-update functionality
++        '''
++        #FIXME: Implment the basename filter
++        pklog.info("Get updates")
++        self.StatusChanged(STATUS_INFO)
++        self.AllowCancel(True)
++        self.NoPercentageUpdates()
++        self._check_init(progress=False)
++        self._cache.upgrade(False)
++        for pkg in self._cache.getChanges():
++            if self._canceled.isSet():
++                self.ErrorCode(ERROR_TRANSACTION_CANCELLED,
++                               "Calculating updates was canceled")
++                self.Finished(EXIT_KILL)
++                self._canceled.clear()
++                return
++            else:
++                self._emit_package(pkg)
++        self._open_cache(progress=False)
++        self.Finished(EXIT_SUCCESS)
++
++    @threaded
++    def GetDetails(self, pkg_id):
++        '''
++        Implement the {backend}-get-details functionality
++        '''
++        pklog.info("Get details of %s" % pkg_id)
++        self.StatusChanged(STATUS_INFO)
++        self.NoPercentageUpdates()
++        self.AllowCancel(False)
++        self._check_init(progress=False)
++        name, version, arch, data = self.get_package_from_id(pkg_id)
++        if not self._cache.has_key(name):
++            self.ErrorCode(ERROR_PACKAGE_NOT_FOUND,
++                           "Package %s isn't available" % name)
++            self.Finished(EXIT_FAILED)
++            return
++        pkg = self._cache[name]
++        #FIXME: should perhaps go to python-apt since we need this in
++        #       several applications
++        desc = pkg.description
++        # Skip the first line - it's a duplicate of the summary
++        i = desc.find('\n')
++        desc = desc[i+1:]
++        # do some regular expression magic on the description
++        # Add a newline before each bullet
++        p = re.compile(r'^(\s|\t)*(\*|0|-)',re.MULTILINE)
++        desc = p.sub(ur'\n\u2022', desc)
++        # replace all newlines by spaces
++        p = re.compile(r'\n', re.MULTILINE)
++        desc = p.sub(" ", desc)
++        # replace all multiple spaces by newlines
++        p = re.compile(r'\s\s+', re.MULTILINE)
++        desc = p.sub('\n', desc)
++        #FIXME: group and licence information missing
++        self.Details(pkg_id, 'unknown', 'unknown', desc,
++                         pkg.homepage, pkg.packageSize)
++        self.Finished(EXIT_SUCCESS)
++
++    @threaded
++    @async
++    def doUpdateSystem(self):
++        '''
++        Implement the {backend}-update-system functionality
++        '''
++        pklog.info("Upgrading system")
++        self.StatusChanged(STATUS_UPDATE)
++        self.AllowCancel(False)
++        self.PercentageChanged(0)
++        self._check_init(prange=(0,5))
++        try:
++            self._cache.upgrade(distUpgrade=False)
++            self._cache.commit(PackageKitFetchProgress(self, prange=(5,50)),
++                               PackageKitInstallProgress(self, prange=(50,95)))
++        except apt.cache.FetchFailedException:
++            self._open_cache()
++            self.ErrorCode(ERROR_PACKAGE_DOWNLOAD_FAILED, "Download failed")
++            self.Finished(EXIT_FAILED)
++            return
++        except apt.cache.FetchCancelledException:
++            self._open_cache(prange=(95,100))
++            self.ErrorCode(ERROR_TRANSACTION_CANCELLED, "Download was canceled")
++            self.Finished(EXIT_KILL)
++            self._canceled.clear()
++            return
++        except:
++            self._open_cache(prange=(95,100))
++            self.ErrorCode(ERROR_UNKNOWN, "System update failed")
++            self.Finished(EXIT_FAILED)
++            return
++        self.PercentageChanged(100)
++        self.Finished(EXIT_SUCCESS)
++
++    @threaded
++    @async
++    def doRemovePackages(self, ids, deps=True, auto=False):
++        '''
++        Implement the {backend}-remove functionality
++        '''
++        pklog.info("Removing package(s): id %s" % ids)
++        self.StatusChanged(STATUS_REMOVE)
++        self.AllowCancel(False)
++        self.PercentageChanged(0)
++        self._check_init(prange=(0,10))
++        pkgs=[]
++        for id in ids:
++            pkg = self._find_package_by_id(id)
++            if pkg == None:
++                self.ErrorCode(ERROR_PACKAGE_NOT_FOUND,
++                               "Package %s isn't available" % id)
++                self.Finished(EXIT_FAILED)
++                return
++            if not pkg.isInstalled:
++                self.ErrorCode(ERROR_PACKAGE_NOT_INSTALLED,
++                               "Package %s isn't installed" % pkg.name)
++                self.Finished(EXIT_FAILED)
++                return
++            pkgs.append(pkg.name[:])
++            try:
++                pkg.markDelete()
++            except:
++                self._open_cache(prange=(90,99))
++                self.ErrorCode(ERROR_UNKNOWN, "Removal of %s failed" % pkg.name)
++                self.Finished(EXIT_FAILED)
++                return
++        try:
++            self._cache.commit(PackageKitFetchProgress(self, prange=(10,10)),
++                               PackageKitInstallProgress(self, prange=(10,90)))
++        except:
++            self._open_cache(prange=(90,99))
++            self.ErrorCode(ERROR_UNKNOWN, "Removal failed")
++            self.Finished(EXIT_FAILED)
++            return
++        self._open_cache(prange=(90,99))
++        for p in pkgs:
++            if self._cache.has_key(p) and self._cache[p].isInstalled:
++                self.ErrorCode(ERROR_UNKNOWN, "%s is still installed" % p)
++                self.Finished(EXIT_FAILED)
++                return
++        self.PercentageChanged(100)
++        self.Finished(EXIT_SUCCESS)
++
++    @threaded
++    @async
++    def doInstallPackages(self, ids):
++        '''
++        Implement the {backend}-install functionality
++        '''
++        pklog.info("Installing package with id %s" % ids)
++        self.StatusChanged(STATUS_INSTALL)
++        self.AllowCancel(False)
++        self.PercentageChanged(0)
++        self._check_init(prange=(0,10))
++        pkgs=[]
++        for id in ids:
++            pkg = self._find_package_by_id(id)
++            if pkg == None:
++                self.ErrorCode(ERROR_PACKAGE_NOT_FOUND,
++                               "Package %s isn't available" % id)
++                self.Finished(EXIT_FAILED)
++                return
++            if pkg.isInstalled:
++                self.ErrorCode(ERROR_PACKAGE_ALREADY_INSTALLED,
++                               "Package %s is already installed" % pkg.name)
++                self.Finished(EXIT_FAILED)
++                return
++            pkgs.append(pkg.name[:])
++            try:
++                pkg.markInstall()
++            except:
++                self._open_cache(prange=(90,100))
++                self.ErrorCode(ERROR_UNKNOWN, "%s could not be queued for "
++                                              "installation" % pkg.name)
++                self.Finished(EXIT_FAILED)
++                return
++        try:
++            self._cache.commit(PackageKitFetchProgress(self, prange=(10,50)),
++                               PackageKitInstallProgress(self, prange=(50,90)))
++        except:
++            self._open_cache(prange=(90,100))
++            self.ErrorCode(ERROR_UNKNOWN, "Installation failed")
++            self.Finished(EXIT_FAILED)
++            return
++        self._open_cache(prange=(90,100))
++        self.PercentageChanged(100)
++        pklog.debug("Checking success of operation")
++        for p in pkgs:
++            if not self._cache.has_key(p) or not self._cache[p].isInstalled:
++                self.ErrorCode(ERROR_UNKNOWN, "%s was not installed" % p)
++                self.Finished(EXIT_FAILED)
++                return
++        pklog.debug("Sending success signal")
++        self.Finished(EXIT_SUCCESS)
++
++    @threaded
++    @async
++    def doRefreshCache(self, force):
++        '''
++        Implement the {backend}-refresh_cache functionality
++        '''
++        pklog.info("Refresh cache")
++        self.StatusChanged(STATUS_REFRESH_CACHE)
++        self.last_action_time = time.time()
++        self.AllowCancel(False);
++        self.PercentageChanged(0)
++        self._check_init((0,10))
++        try:
++            self._cache.update(PackageKitFetchProgress(self, prange=(10,95)))
++        except apt.cache.FetchFailedException:
++            self.ErrorCode(ERROR_NO_NETWORK, "Download failed")
++            self.Finished(EXIT_FAILED)
++            return
++        except apt.cache.FetchCancelledException:
++            self._canceled.clear()
++            self.ErrorCode(ERROR_TRANSACTION_CANCELLED, "Download was canceled")
++            self.Finished(EXIT_KILL)
++            return
++        except:
++            self._open_cache(prange=(95,100))
++            self.ErrorCode(ERROR_UNKNOWN, "Refreshing cache failed")
++            self.Finished(EXIT_FAILED)
++            return
++        self.PercentageChanged(100)
++        self.Finished(EXIT_SUCCESS)
++
++    @threaded
++    def doGetPackages(self, filters):
++        '''
++        Implement the apt2-get-packages functionality
++        '''
++        pklog.info("Get all packages")
++        self.StatusChanged(STATUS_QUERY)
++        self.NoPercentageUpdates()
++        self._check_init(progress=False)
++        self.AllowCancel(True)
++
++        for pkg in self._cache:
++            if self._canceled.isSet():
++                self.ErrorCode(ERROR_TRANSACTION_CANCELLED,
++                               "The search was canceled")
++                self.Finished(EXIT_KILL)
++                self._canceled.clear()
++                return
++            elif self._is_package_visible(pkg, filters):
++                self._emit_package(pkg)
++        self.Finished(EXIT_SUCCESS)
++
++    @threaded
++    def doResolve(self, filters, name):
++        '''
++        Implement the apt2-resolve functionality
++        '''
++        pklog.info("Resolve")
++        self.StatusChanged(STATUS_QUERY)
++        self.NoPercentageUpdates()
++        self._check_init(progress=False)
++        self.AllowCancel(False)
++
++        #FIXME: Support candidates
++        if self._cache.has_key(name) and self.is_package_visible(pkg, filters):
++            self._emit_package(name)
++            self.Finished(EXIT_SUCCESS)
++        else:
++            self.ErrorCode(ERROR_PACKAGE_NOT_FOUND,
++                           "Package name %s could not be resolved" % name)
++            self.Finished(EXIT_FAILED)
++
++    # Helpers
++
++    def _open_cache(self, prange=(0,100), progress=True):
++        '''
++        (Re)Open the APT cache
++        '''
++        pklog.debug("Open APT cache")
++        self.StatusChanged(STATUS_REFRESH_CACHE)
++        try:
++            self._cache = apt.Cache(PackageKitOpProgress(self, prange,
++                                                         progress))
++        except:
++            self.ErrorCode(ERROR_NO_CACHE, "Package cache could not be opened")
++            self.Finished(EXIT_FAILED)
++            self.Exit()
++            return
++        if self._cache._depcache.BrokenCount > 0:
++            self.ErrorCode(ERROR_DEP_RESOLUTION_FAILED,
++                           "Not all dependecies can be satisfied")
++            self.Finished(EXIT_FAILED)
++            self.Exit()
++            return
++
++    def _lock_cache(self):
++        '''
++        Lock the cache
++        '''
++        pklog.debug("Locking cache")
++        self._locked.acquire()
++
++    def _unlock_cache(self):
++        '''
++        Unlock the cache
++        '''
++        pklog.debug("Releasing cache")
++        self._locked.release()
++
++    def _check_init(self, prange=(0,10), progress=True):
++        '''
++        Check if the backend was initialized well and try to recover from
++        a broken setup
++        '''
++        pklog.debug("Check apt cache and xapian database")
++        if not isinstance(self._cache, apt.cache.Cache) or \
++           self._cache._depcache.BrokenCount > 0:
++            self._open_cache(prange, progress)
++
++    def _check_canceled(self, msg):
++        '''
++        Check if the current transaction was canceled. If so send the
++        corresponding error message and return True
++        '''
++        if self._canceled.isSet():
++             self.ErrorCode(ERROR_TRANSACTION_CANCELLED, msg)
++             self.Finished(EXIT_KILL)
++             self._canceled.clear()
++             return True
++        return False
++ 
++    def get_id_from_package(self, pkg, installed=False):
++        '''
++        Return the id of the installation candidate of a core
++        apt package. If installed is set to True the id of the currently
++        installed package will be returned.
++        '''
++        origin = ''
++        if installed == False and pkg.isInstalled:
++            pkgver = pkg.installedVersion
++        else:
++            pkgver = pkg.candidateVersion
++            if pkg.candidateOrigin:
++                origin = pkg.candidateOrigin[0].label
++        id = self._get_package_id(pkg.name, pkgver, pkg.architecture, origin)
++        return id
++
++    def _emit_package(self, pkg):
++        '''
++        Send the Package signal for a given apt package
++        '''
++        id = self.get_id_from_package(pkg)
++        if pkg.isInstalled:
++            status = INFO_INSTALLED
++        else:
++            status = INFO_AVAILABLE
++        summary = pkg.summary
++        self.Package(status, id, summary)
++
++    def _is_package_visible(self, pkg, filters):
++        '''
++        Return True if the package should be shown in the user interface
++        '''
++        #FIXME: Needs to be optmized
++        if filters == 'none':
++            return True
++        if FILTER_INSTALLED in filters and not pkg.isInstalled:
++            return False
++        if FILTER_NOT_INSTALLED in filters and pkg.isInstalled:
++            return False
++        if FILTER_GUI in filters and not self._package_has_gui(pkg):
++            return False
++        if FILTER_NOT_GUI in filters and self._package_has_gui(pkg):
++            return False
++        if FILTER_DEVELOPMENT in filters and not self._package_is_devel(pkg):
++            return False
++        if FILTER_NOT_DEVELOPMENT in filters and self._package_is_devel(pkg):
++            return False
++        return True
++
++    def _package_has_gui(self, pkg):
++        #FIXME: should go to a modified Package class
++        #FIXME: take application data into account. perhaps checking for
++        #       property in the xapian database
++        return pkg.section.split('/')[-1].lower() in ['x11', 'gnome', 'kde']
++
++    def _package_is_devel(self, pkg):
++        #FIXME: should go to a modified Package class
++        return pkg.name.endswith("-dev") or pkg.name.endswith("-dbg") or \
++               pkg.section.split('/')[-1].lower() in ['devel', 'libdevel']
++
++    def _find_package_by_id(self, id):
++        '''
++        Return a package matching to the given package id
++        '''
++        # FIXME: Perform more checks
++        name, version, arch, data = self.get_package_from_id(id)
++        if self._cache.has_key(name):
++            return self._cache[name]
++        else:
++            return None
++
++
++def main():
++    loop = dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
++    bus = dbus.SystemBus(mainloop=loop)
++    bus_name = dbus.service.BusName(PACKAGEKIT_DBUS_SERVICE, bus=bus)
++    manager = PackageKitAptBackend(bus_name, PACKAGEKIT_DBUS_PATH)
++
++if __name__ == '__main__':
++    main()
++
++# vim: ts=4 et sts=4
+diff --git a/backends/apt/helpers/.gitignore b/backends/apt/helpers/.gitignore
+deleted file mode 100644
+index 0d20b64..0000000
+--- a/backends/apt/helpers/.gitignore
++++ /dev/null
+@@ -1 +0,0 @@
+-*.pyc
+diff --git a/backends/apt/helpers/Makefile.am b/backends/apt/helpers/Makefile.am
+deleted file mode 100644
+index 0299df2..0000000
+--- a/backends/apt/helpers/Makefile.am
++++ /dev/null
+@@ -1,29 +0,0 @@
+-
+-helperdir = $(datadir)/PackageKit/helpers/apt
+-
+-NULL =
+-
+-dist_helper_DATA =                    \
+-      install-files.py                \
+-      search-name.py                  \
+-      search-details.py               \
+-      search-group.py                 \
+-      search-file.py                  \
+-      get-depends.py                  \
+-      get-details.py                  \
+-      get-repo-list.py                \
+-      get-requires.py                 \
+-      get-update-detail.py            \
+-      get-updates.py                  \
+-      refresh-cache.py                \
+-      repo-enable.py                  \
+-      resolve.py                      \
+-      aptBackend.py                   \
+-      $(NULL)
+-
+-install-data-hook:
+-      chmod a+rx $(DESTDIR)$(helperdir)/*.py
+-
+-clean-local :
+-      rm -f *~
+-
+diff --git a/backends/apt/helpers/aptBackend.py b/backends/apt/helpers/aptBackend.py
+deleted file mode 100644
+index e5f78ca..0000000
+--- a/backends/apt/helpers/aptBackend.py
++++ /dev/null
+@@ -1,536 +0,0 @@
+-#
+-# vim: ts=4 et sts=4
+-#
+-# Copyright (C) 2007 Ali Sabil <ali.sabil@gmail.com>
+-# Copyright (C) 2007 Tom Parker <palfrey@tevp.net>
+-#
+-# Licensed under the GNU General Public License Version 2
+-#
+-# 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 2 of the License, or
+-# (at your option) any later version.
+-
+-import sys
+-import os
+-import re
+-
+-from packagekit.backend import *
+-import apt_pkg,apt_inst
+-
+-import warnings
+-warnings.filterwarnings(action='ignore', category=FutureWarning)
+-import apt
+-from aptsources.distro import get_distro
+-from aptsources.sourceslist import SourcesList
+-from sets import Set
+-from os.path import join,exists
+-from urlparse import urlparse
+-from apt.debfile import DebPackage
+-from os import system
+-
+-class Package(apt.Package):
+-    def __str__(self):
+-        return "Package %s, version %s"%(self.name,self._version)
+-
+-    def _cmp_deps(self,deps, version):
+-        for (v,c) in deps:
+-            if not apt_pkg.CheckDep(version,c,v):
+-                return False
+-        return True
+-
+-    def __init__(self, backend, pkg, data="",version=[]):
+-        apt.package.Package.__init__(self, pkg._cache, pkg._depcache,
+-                                     pkg._records, pkg._list, pkg._pcache,
+-                                     pkg._pkg)
+-        self._version = version
+-        self._data = data
+-        self._backend = backend
+-        wanted_ver = None
+-        if self.installedVersion!=None and self._cmp_deps(version,self.installedVersion):
+-            wanted_ver = self.installedVersion
+-        elif self.installedVersion == None and version == []:
+-            #self.markInstall(False,False)
+-            wanted_ver = self.candidateVersion
+-
+-        for ver in pkg._pkg.VersionList:
+-            #print "vers",dir(ver),version,ver
+-            #print data
+-            if (wanted_ver == None or wanted_ver == ver.VerStr) and self._cmp_deps(version,ver.VerStr):
+-                f, index = ver.FileList.pop(0)
+-                if self._data == "":
+-                    if f.Origin=="" and f.Archive=="now":
+-                        self._data = "local_install"
+-                    elif f.Origin!="" or f.Archive!="":
+-                        self._data = "%s/%s"%(f.Origin.replace("/","_"),f.Archive.replace("/","_"))
+-                    else:
+-                        self._data = "%s/unknown"%f.Site
+-                self._version = ver.VerStr
+-                break
+-        else:
+-            print "wanted",wanted_ver
+-            for ver in pkg._pkg.VersionList:
+-                print "vers",version,ver.VerStr
+-            backend.error(ERROR_PACKAGE_NOT_FOUND, "Can't find version %s for %s"%(version,self.name))
+-
+-    def setVersion(self,version,compare="="):
+-        if version!=None and (self.installedVersion == None or not apt_pkg.CheckDep(version,compare,self.installedVersion)):
+-            self.markInstall(False,False)
+-            if self.candidateVersion != version:
+-                if self._data == "":
+-                    for ver in pkg._pkg.VersionList:
+-                        f, index = ver.FileList.pop(0)
+-                        self._data = "%s/%s"%(f.Origin,f.Archive)
+-                        if ver.VerStr == version:
+-                            break
+-
+-                # FIXME: this is a nasty hack, assuming that the best way to resolve
+-                # deps for non-default repos is by switching the default release.
+-                # We really need a better resolver (but that's hard)
+-                assert self._data!=""
+-                origin = self._data[self._data.find("/")+1:]
+-                print "origin",origin
+-                name = self.name
+-                apt_pkg.Config.Set("APT::Default-Release",origin)
+-                if not self._backend._caches.has_key(origin):
+-                    self._backend._caches[origin] = apt.Cache(PackageKitProgress(self))
+-                    print "new cache for %s"%origin
+-                self.__setParent(self._backend._caches[origin][name])
+-                self.markInstall(False,False)
+-                if not apt_pkg.CheckDep(self.candidateVersion,compare,version):
+-                    self._backend.error(ERROR_PACKAGE_NOT_FOUND,
+-                            "Unable to locate package version %s (only got %s) for %s"%(version,self.candidateVersion,name))
+-                    return
+-                self.markKeep()
+-
+-    @property
+-    def group(self):
+-        section = self.section.split('/')[-1].lower()
+-        #if section in ():
+-        #    return GROUP_ACCESSIBILITY
+-        if section in ('utils',):
+-            return "accessories"
+-        #if section in ():
+-        #    return GROUP_EDUCATION
+-        if section in ('games',):
+-            return "games"
+-        if section in ('graphics',):
+-            return "graphics"
+-        if section in ('net', 'news', 'web', 'comm'):
+-            return "internet"
+-        if section in ('editors', 'tex'):
+-            return "office"
+-        if section in ('misc',):
+-            return "other"
+-        if section in ('devel', 'libdevel', 'interpreters', 'perl', 'python'):
+-            return "programming"
+-        if section in ('sound',):
+-            return "multimedia"
+-        if section in ('base', 'admin'):
+-            return "system"
+-        return "unknown"
+-
+-    @property
+-    def isInstalled(self):
+-        return super(self.__class__,self).isInstalled and self.installedVersion == self._version
+-
+-    @property
+-    def isDevelopment(self):
+-        name = self.name.lower()
+-        section = self.section.split('/')[-1].lower()
+-        return name.endswith('-dev') or name.endswith('-dbg') or \
+-                section in ('devel', 'libdevel')
+-
+-    @property
+-    def isGui(self):
+-        section = self.section.split('/')[-1].lower()
+-        return section in ('x11', 'gnome', 'kde')
+-
+-    _HYPHEN_PATTERN = re.compile(r'(\s|_)+')
+-
+-    def matchName(self, name):
+-        needle = name.strip().lower()
+-        haystack = self.name.lower()
+-        needle = Package._HYPHEN_PATTERN.sub('-', needle)
+-        haystack = Package._HYPHEN_PATTERN.sub('-', haystack)
+-        if haystack.find(needle) >= 0:
+-            return True
+-        return False
+-
+-    def matchDetails(self, details):
+-        if self.matchName(details):
+-            return True
+-        needle = details.strip().lower()
+-        haystack = self.description.lower()
+-        if haystack.find(needle) >= 0:
+-            return True
+-        return False
+-
+-    def matchGroup(self, name):
+-        needle = name.strip().lower()
+-        haystack = self.group
+-        if haystack.startswith(needle):
+-            return True
+-        return False
+-
+-class PackageKitProgress(apt.progress.OpProgress, apt.progress.FetchProgress):
+-    def __init__(self, backend):
+-        self._backend = backend
+-        apt.progress.OpProgress.__init__(self)
+-        apt.progress.FetchProgress.__init__(self)
+-
+-    # OpProgress callbacks
+-    def update(self, percent):
+-        pass
+-
+-    def done(self):
+-        pass
+-
+-    # FetchProgress callbacks
+-    def pulse(self):
+-        apt.progress.FetchProgress.pulse(self)
+-        self._backend.percentage(self.percent)
+-        return True
+-
+-    def stop(self):
+-        self._backend.percentage(100)
+-
+-    def mediaChange(self, medium, drive):
+-        # This probably should not be an error, but a Message.
+-        self._backend.error(ERROR_UNKNOWN,
+-                "Medium change needed")
+-
+-class PackageKitAptBackend(PackageKitBaseBackend):
+-    def __init__(self, args):
+-        PackageKitBaseBackend.__init__(self, args)
+-        self.status(STATUS_SETUP)
+-        self._caches  = {}
+-        self._apt_cache = apt.Cache(PackageKitProgress(self))
+-        default = apt_pkg.Config.Find("APT::Default-Release")
+-        if default=="":
+-            d = get_distro()
+-            if d.id == "Debian":
+-                default = "stable"
+-            elif d.id == "Ubuntu":
+-                default = "main"
+-            else:
+-                raise Exception,d.id
+-
+-        self._caches[default] = self._apt_cache
+-
+-
+-    def search_name(self, filters, key):
+-        '''
+-        Implement the {backend}-search-name functionality
+-        '''
+-        self.status(STATUS_INFO)
+-        self.allow_cancel(True)
+-        for package in self._do_search(filters,
+-                lambda pkg: pkg.matchName(key)):
+-            self._emit_package(package)
+-
+-    def search_details(self, filters, key):
+-        '''
+-        Implement the {backend}-search-details functionality
+-        '''
+-        self.status(STATUS_INFO)
+-        self.allow_cancel(True)
+-        for package in self._do_search(filters,
+-                lambda pkg: pkg.matchDetails(key)):
+-            self._emit_package(package)
+-
+-    def search_group(self, filters, key):
+-        '''
+-        Implement the {backend}-search-group functionality
+-        '''
+-        self.status(STATUS_INFO)
+-        self.allow_cancel(True)
+-        for package in self._do_search(filters,
+-                lambda pkg: pkg.matchGroup(key)):
+-            self._emit_package(package)
+-
+-    def search_file(self, filters, key):
+-        '''
+-        Implement the {backend}-search-file functionality
+-        '''
+-        self.allow_cancel(True)
+-        self.percentage(None)
+-
+-        self.error(ERROR_NOT_SUPPORTED,
+-                "This function is not implemented in this backend")
+-
+-    def refresh_cache(self):
+-        '''
+-        Implement the {backend}-refresh_cache functionality
+-        '''
+-        self.status(STATUS_REFRESH_CACHE)
+-        try:
+-            res = self._apt_cache.update(PackageKitProgress(self))
+-        except Exception, error_message:
+-             self.error(ERROR_UNKNOWN,
+-                        "Failed to fetch the following items:\n%s" % error_message)
+-        return res
+-
+-    def get_details(self, package):
+-        '''
+-        Implement the {backend}-get-details functionality
+-        '''
+-        self.status(STATUS_INFO)
+-        name, version, arch, data = self.get_package_from_id(package)
+-        pkg = Package(self, self._apt_cache[name])
+-        description = re.sub('\s+', ' ', pkg.description).strip()
+-        self.description(package, 'unknown', pkg.group, description,
+-                         pkg.architecture, pkg.packageSize)
+-
+-    def resolve(self, name):
+-        '''
+-        Implement the {backend}-resolve functionality
+-        '''
+-        self.status(STATUS_INFO)
+-        try:
+-            pkg = Package(self,self._apt_cache[name])
+-            self._emit_package(pkg)
+-        except KeyError:
+-            self.error(ERROR_PACKAGE_NOT_FOUND,"Can't find a package called '%s'"%name)
+-
+-    def _do_deps(self,inp,deps,recursive):
+-        inp.markInstall()
+-        newkeys = []
+-        for x in inp.candidateDependencies:
+-            n = x.or_dependencies[0].name
+-            if not deps.has_key(n):
+-                deps[n] = []
+-                newkeys.append(n)
+-            deps[n].append((x.or_dependencies[0].version,x.or_dependencies[0].relation))
+-        if recursive:
+-            for n in newkeys:
+-                try:
+-                    deps = self._do_deps(Package(self,self._apt_cache[n],version=deps[n]),deps,recursive)
+-                except KeyError: # FIXME: we're assuming this is a virtual package, which we can't cope with yet
+-                    del deps[n]
+-                    continue
+-        return deps
+-
+-    def get_depends(self,filters,package, recursive):
+-        '''
+-        Implement the {backend}-get-depends functionality
+-        '''
+-        self.allow_cancel(True)
+-        self.status(STATUS_INFO)
+-        recursive = (recursive == "True")
+-        name, version, arch, data = self.get_package_from_id(package)
+-        pkg = Package(self,self._apt_cache[name],version=[(version,"=")],data=data)
+-        pkg.setVersion(version)
+-        deps = self._do_deps(pkg, {}, recursive)
+-        for n in deps.keys():
+-           self._emit_package(Package(self,self._apt_cache[n],version=deps[n]))
+-
+-    def _do_reqs(self,inp,pkgs,recursive):
+-        extra = []
+-        fails = []
+-        for r in inp._pkg.RevDependsList:
+-            ch = apt_pkg.CheckDep(inp._version,r.CompType,r.TargetVer)
+-            v = (r.ParentPkg.Name,r.ParentVer.VerStr)
+-            if not ch or v in fails:
+-                #print "skip",r.TargetVer,r.CompType,r.ParentPkg.Name,r.ParentVer.VerStr
+-                fails.append(v)
+-                continue
+-            p = Package(self,self._apt_cache[r.ParentPkg.Name],r.ParentVer.VerStr)
+-            if v not in pkgs:
+-                extra.append(p)
+-                #print "new pkg",p
+-                self._emit_package(p)
+-            pkgs.add(v)
+-        if recursive:
+-            for e in extra:
+-                pkgs = self._do_reqs(p, pkgs,recursive)
+-        return pkgs
+-
+-    def get_requires(self,package,recursive):
+-        '''
+-        Implement the {backend}-get-requires functionality
+-        '''
+-        self.allow_cancel(True)
+-        self.status(STATUS_INFO)
+-        recursive = (recursive == "True")
+-        name, version, arch, data = self.get_package_from_id(package)
+-        pkg = Package(self,self._apt_cache[name], version=[(version,"=")], data=data)
+-
+-        pkgs = Set()
+-        self._do_reqs(pkg,pkgs, recursive)
+-
+-    def _build_repo_list(self):
+-        repo = {}
+-
+-        sources = SourcesList()
+-        repo["__sources"] = sources
+-
+-        root = apt_pkg.Config.FindDir("Dir::State::Lists")
+-        #print root
+-        for entry in sources:
+-            if entry.type!="":
+-                url = entry.uri
+-                #if entry.template!=None:
+-                url +="/dists/"
+-                url += entry.dist
+-                url = url.replace("//dists","/dists")
+-                #print url
+-                path = join(root,"%s_Release"%(apt_pkg.URItoFileName(url)))
+-                if not exists(path):
+-                    #print path
+-                    name = "%s/unknown"%urlparse(entry.uri)[1]
+-                else:
+-                    lines = file(path).readlines()
+-                    origin = ""
+-                    suite = ""
+-                    for l in lines:
+-                        if l.find("Origin: ")==0:
+-                            origin = l.split(" ",1)[1].strip()
+-                        elif l.find("Suite: ")==0:
+-                            suite = l.split(" ",1)[1].strip()
+-                    assert origin!="" and suite!=""
+-                    name = "%s/%s"%(origin,suite)
+-                if entry.type == "deb-src":
+-                    name += "-src"
+-
+-                repo[name] = {"entry":entry}
+-        return repo
+-
+-    def get_repo_list(self, filters):
+-        '''
+-        Implement the {backend}-get-repo-list functionality
+-        '''
+-        self.allow_interrupt(True)
+-        self.status(STATUS_INFO)
+-        repo = self._build_repo_list()
+-        for e in repo.keys():
+-            if e == "__sources":
+-                continue
+-            self.repo_detail(repo[e]["entry"].line.strip(),e,not repo[e]["entry"].disabled)
+-
+-    def repo_enable(self, repoid, enable):
+-        '''
+-        Implement the {backend}-repo-enable functionality
+-        '''
+-        enable = (enable == "True")
+-        repo = self._build_repo_list()
+-        if not repo.has_key(repoid):
+-            self.error(ERROR_REPO_NOT_FOUND,"Couldn't find repo '%s'"%repoid)
+-            return
+-        r = repo[repoid]
+-        if not r["entry"].disabled == enable: # already there
+-            return
+-        r["entry"].set_enabled(enable)
+-        try:
+-            repo["__sources"].save()
+-        except IOError,e:
+-            self.error(ERROR_UNKNOWN, "Problem while trying to save repo settings to %s: %s"%(e.filename,e.strerror))
+-
+-    def get_updates(self, filter):
+-        self._apt_cache.upgrade(False)
+-        for pkg in self._apt_cache.getChanges():
+-            self._emit_package(Package(self, pkg))
+-
+-    def get_update_detail(self, package):
+-        self.allow_cancel(True)
+-        self.percentage(None)
+-        self.status(STATUS_INFO)
+-        name, version, arch, data = self.get_package_from_id(package)
+-        update = ""
+-        obsolete = ""
+-        cve_url = ""
+-        bz_url = ""
+-        vendor_url = ""
+-        reboot = "none"
+-        desc = self._apt_cache[name].description
+-        self.update_detail(package,update,obsolete,vendor_url,bz_url,cve_url,reboot,desc)
+-
+-
+-    def install_files (self, inst_files):
+-        '''
+-        Implement the {backend}-install_files functionality
+-        Install the package containing the inst_file file
+-        '''
+-        if not exists(inst_file):
+-            self.error(ERROR_PACKAGE_NOT_FOUND,"Can't find %s"%inst_file)
+-            return
+-        deb = DebPackage(inst_file)
+-        deps = {}
+-        for k in ["Depends","Recommends"]:
+-            if not deb._sections.has_key(k):
+-                continue
+-            for items in apt_pkg.ParseDepends(deb[k]):
+-                assert len(items) == 1,"Can't handle or deps properly yet"
+-                (pkg,ver,comp) = items[0]
+-                if not deps.has_key(pkg):
+-                    deps[pkg] = []
+-                deps[pkg].append((ver,comp))
+-        for n in deps.keys():
+-           p = Package(self,self._apt_cache[n],version=deps[n])
+-           if not p.isInstalled:
+-               p.markInstall()
+-        assert self._apt_cache.getChanges()==[],"Don't handle install changes yet"
+-        # FIXME: nasty hack. Need a better way in
+-        ret = system("dpkg -i %s"%inst_file)
+-        if ret!=0:
+-            self.error(ERROR_UNKNOWN,"Can't install package")
+-
+-    ### Helpers ###
+-    def _emit_package(self, package):
+-        id = self.get_package_id(package.name,
+-                package._version,
+-                package.architecture,
+-                package._data)
+-        if package.isInstalled:
+-            status = INFO_INSTALLED
+-        else:
+-            status = INFO_AVAILABLE
+-        summary = package.summary
+-        self.package(id, status, summary)
+-
+-    def _do_search(self, filters, condition):
+-        filters = filters.split(';')
+-        size = len(self._apt_cache)
+-        percentage = 0
+-        for i, pkg in enumerate(self._apt_cache):
+-            new_percentage = i / float(size) * 100
+-            if new_percentage - percentage >= 5:
+-                percentage = new_percentage
+-                self.percentage(percentage)
+-            package = Package(self, pkg)
+-            if package.installedVersion is None and \
+-                    package.candidateVersion is None:
+-                continue
+-            if not condition(package):
+-                continue
+-                continue
+-            vers = [x.VerStr for x in package._pkg.VersionList]
+-            if package.installedVersion!=None:
+-                i = package.installedVersion
+-                if i in vers and vers[0]!=i:
+-                    del vers[vers.index(i)]
+-                    vers.insert(0,i)
+-
+-            for ver in vers:
+-                p = Package(self, package, version=[[ver,"="]])
+-                if self._do_filtering(p, filters):
+-                    yield p
+-        self.percentage(100)
+-
+-    def _do_filtering(self, package, filters):
+-        if len(filters) == 0 or filters == ['none']:
+-            return True
+-        if (FILTER_INSTALLED in filters) and (not package.isInstalled):
+-            return False
+-        if (FILTER_NOT_INSTALLED in filters) and package.isInstalled:
+-            return False
+-        if (FILTER_GUI in filters) and (not package.isGui):
+-            return False
+-        if (FILTER_NOT_GUI in filters) and package.isGui:
+-            return False
+-        if (FILTER_DEVELOPMENT in filters) and (not package.isDevelopment):
+-            return False
+-        if (FILTER_NOT_DEVELOPMENT in filters) and package.isDevelopment:
+-            return False
+-        return True
+-
+diff --git a/backends/apt/helpers/get-depends.py b/backends/apt/helpers/get-depends.py
+deleted file mode 100755
+index 94dca4a..0000000
+--- a/backends/apt/helpers/get-depends.py
++++ /dev/null
+@@ -1,20 +0,0 @@
+-#!/usr/bin/python
+-#
+-# Copyright (C) 2007 Richard Hughes <richard@hughsie.com>
+-#
+-# Licensed under the GNU General Public License Version 2
+-#
+-# 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 2 of the License, or
+-# (at your option) any later version.
+-
+-import sys
+-
+-from aptBackend import PackageKitAptBackend
+-filters=sys.argv[1]
+-package=sys.argv[2]
+-recursive = sys.argv[3]
+-backend = PackageKitAptBackend(sys.argv[1:])
+-backend.get_depends(filters, package, recursive)
+-sys.exit(0)
+diff --git a/backends/apt/helpers/get-details.py b/backends/apt/helpers/get-details.py
+deleted file mode 100755
+index a813640..0000000
+--- a/backends/apt/helpers/get-details.py
++++ /dev/null
+@@ -1,18 +0,0 @@
+-#!/usr/bin/python
+-#
+-# Copyright (C) 2007 Ali Sabil <ali.sabil@gmail.com>
+-#
+-# Licensed under the GNU General Public License Version 2
+-#
+-# 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 2 of the License, or
+-# (at your option) any later version.
+-
+-import sys
+-from aptBackend import PackageKitAptBackend
+-
+-package = sys.argv[1]
+-backend = PackageKitAptBackend(sys.argv[1:])
+-backend.get_details(package)
+-sys.exit(0)
+diff --git a/backends/apt/helpers/get-repo-list.py b/backends/apt/helpers/get-repo-list.py
+deleted file mode 100755
+index 5529f72..0000000
+--- a/backends/apt/helpers/get-repo-list.py
++++ /dev/null
+@@ -1,20 +0,0 @@
+-#!/usr/bin/python
+-#
+-# Copyright (C) 2007 Richard Hughes <richard@hughsie.com>
+-#
+-# Licensed under the GNU General Public License Version 2
+-#
+-# 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 2 of the License, or
+-# (at your option) any later version.
+-
+-import sys
+-
+-from aptBackend import PackageKitAptBackend
+-filters = sys.argv[1]
+-
+-backend = PackageKitAptBackend(sys.argv[2:])
+-backend.get_repo_list(filters)
+-backend.unLock()
+-sys.exit(0)
+diff --git a/backends/apt/helpers/get-requires.py b/backends/apt/helpers/get-requires.py
+deleted file mode 100755
+index e581010..0000000
+--- a/backends/apt/helpers/get-requires.py
++++ /dev/null
+@@ -1,20 +0,0 @@
+-#!/usr/bin/python
+-#
+-# Copyright (C) 2007 Richard Hughes <richard@hughsie.com>
+-#
+-# Licensed under the GNU General Public License Version 2
+-#
+-# 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 2 of the License, or
+-# (at your option) any later version.
+-
+-import sys
+-
+-from aptBackend import PackageKitAptBackend
+-package = sys.argv[1]
+-recursive = sys.argv[2]
+-
+-backend = PackageKitAptBackend(sys.argv[1:])
+-backend.get_requires(package, recursive)
+-sys.exit(0)
+diff --git a/backends/apt/helpers/get-update-detail.py b/backends/apt/helpers/get-update-detail.py
+deleted file mode 100755
+index 5524d9a..0000000
+--- a/backends/apt/helpers/get-update-detail.py
++++ /dev/null
+@@ -1,18 +0,0 @@
+-#!/usr/bin/python
+-#
+-# Copyright (C) 2008 Michael Vogt <mvo@ubuntu.com>
+-#
+-# Licensed under the GNU General Public License Version 2
+-#
+-# 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 2 of the License, or
+-# (at your option) any later version.
+-
+-import sys
+-
+-from aptBackend import PackageKitAptBackend
+-package=sys.argv[1]
+-backend = PackageKitAptBackend(sys.argv[2:])
+-backend.get_update_detail(package)
+-sys.exit(0)
+diff --git a/backends/apt/helpers/get-updates.py b/backends/apt/helpers/get-updates.py
+deleted file mode 100755
+index 4f45fbf..0000000
+--- a/backends/apt/helpers/get-updates.py
++++ /dev/null
+@@ -1,19 +0,0 @@
+-#!/usr/bin/python
+-#
+-# Copyright (C) 2008 Michael Vogt <mvo@ubuntu.com>
+-#
+-# Licensed under the GNU General Public License Version 2
+-#
+-# 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 2 of the License, or
+-# (at your option) any later version.
+-
+-import sys
+-from aptBackend import PackageKitAptBackend
+-
+-filter = sys.argv[1]
+-
+-backend = PackageKitAptBackend(sys.argv[1:])
+-backend.get_updates(filter)
+-sys.exit(0)
+diff --git a/backends/apt/helpers/install-files.py b/backends/apt/helpers/install-files.py
+deleted file mode 100755
+index dfa024c..0000000
+--- a/backends/apt/helpers/install-files.py
++++ /dev/null
+@@ -1,21 +0,0 @@
+-#!/usr/bin/python
+-#
+-# Copyright (C) 2007 Richard Hughes <richard@hughsie.com>
+-# Copyright (C) 2007 Red Hat Inc, Seth Vidal <skvidal@fedoraproject.org>
+-#
+-# Licensed under the GNU General Public License Version 2
+-#
+-# 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 2 of the License, or
+-# (at your option) any later version.
+-
+-import sys
+-
+-from aptBackend import PackageKitAptBackend
+-
+-trusted = sys.argv[1]
+-files_to_inst = sys.argv[2:]
+-backend = PackageKitAptBackend(sys.argv[1:])
+-backend.install_files(trusted, files_to_inst)
+-sys.exit(0)
+diff --git a/backends/apt/helpers/refresh-cache.py b/backends/apt/helpers/refresh-cache.py
+deleted file mode 100755
+index 881479d..0000000
+--- a/backends/apt/helpers/refresh-cache.py
++++ /dev/null
+@@ -1,17 +0,0 @@
+-#!/usr/bin/python
+-#
+-# Copyright (C) 2007 Ali Sabil <ali.sabil@gmail.com>
+-#
+-# Licensed under the GNU General Public License Version 2
+-#
+-# 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 2 of the License, or
+-# (at your option) any later version.
+-
+-import sys
+-from aptBackend import PackageKitAptBackend
+-
+-backend = PackageKitAptBackend(sys.argv[1:])
+-backend.refresh_cache()
+-sys.exit(0)
+diff --git a/backends/apt/helpers/repo-enable.py b/backends/apt/helpers/repo-enable.py
+deleted file mode 100755
+index 3cc36ae..0000000
+--- a/backends/apt/helpers/repo-enable.py
++++ /dev/null
+@@ -1,20 +0,0 @@
+-#!/usr/bin/python
+-#
+-# Copyright (C) 2007 Richard Hughes <richard@hughsie.com>
+-#
+-# Licensed under the GNU General Public License Version 2
+-#
+-# 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 2 of the License, or
+-# (at your option) any later version.
+-
+-import sys
+-
+-from aptBackend import PackageKitAptBackend
+-repoid = sys.argv[1]
+-state=sys.argv[2]
+-backend = PackageKitAptBackend(sys.argv[2:])
+-backend.repo_enable(repoid,state)
+-backend.unLock()
+-sys.exit(0)
+diff --git a/backends/apt/helpers/resolve.py b/backends/apt/helpers/resolve.py
+deleted file mode 100755
+index aac34df..0000000
+--- a/backends/apt/helpers/resolve.py
++++ /dev/null
+@@ -1,20 +0,0 @@
+-#!/usr/bin/python
+-#
+-# Copyright (C) 2007 Richard Hughes <richard@hughsie.com>
+-#
+-# Licensed under the GNU General Public License Version 2
+-#
+-# 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 2 of the License, or
+-# (at your option) any later version.
+-
+-import sys
+-
+-from aptBackend import PackageKitAptBackend
+-filters = sys.argv[1]
+-name=sys.argv[2]
+-backend = PackageKitAptBackend(sys.argv[2:])
+-backend.resolve(name)
+-backend.unLock()
+-sys.exit(0)
+diff --git a/backends/apt/helpers/search-details.py b/backends/apt/helpers/search-details.py
+deleted file mode 100755
+index d02f1b0..0000000
+--- a/backends/apt/helpers/search-details.py
++++ /dev/null
+@@ -1,21 +0,0 @@
+-#!/usr/bin/python
+-#
+-# Copyright (C) 2007 Ali Sabil <ali.sabil@gmail.com>
+-#
+-# Licensed under the GNU General Public License Version 2
+-#
+-# 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 2 of the License, or
+-# (at your option) any later version.
+-
+-import sys
+-
+-options = sys.argv[1]
+-searchlist = sys.argv[2]
+-
+-from aptBackend import PackageKitAptBackend
+-
+-backend = PackageKitAptBackend(sys.argv[1:])
+-backend.search_details(options,searchlist)
+-sys.exit(0)
+diff --git a/backends/apt/helpers/search-file.py b/backends/apt/helpers/search-file.py
+deleted file mode 100755
+index ec60319..0000000
+--- a/backends/apt/helpers/search-file.py
++++ /dev/null
+@@ -1,21 +0,0 @@
+-#!/usr/bin/python
+-#
+-# Copyright (C) 2007 Ali Sabil <ali.sabil@gmail.com>
+-#
+-# Licensed under the GNU General Public License Version 2
+-#
+-# 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 2 of the License, or
+-# (at your option) any later version.
+-
+-import sys
+-
+-options = sys.argv[1]
+-searchlist = sys.argv[2]
+-
+-from aptBackend import PackageKitAptBackend
+-
+-backend = PackageKitAptBackend(sys.argv[1:])
+-backend.search_file(options,searchlist)
+-sys.exit(0)
+diff --git a/backends/apt/helpers/search-group.py b/backends/apt/helpers/search-group.py
+deleted file mode 100755
+index f63ee80..0000000
+--- a/backends/apt/helpers/search-group.py
++++ /dev/null
+@@ -1,21 +0,0 @@
+-#!/usr/bin/python
+-#
+-# Copyright (C) 2007 Ali Sabil <ali.sabil@gmail.com>
+-#
+-# Licensed under the GNU General Public License Version 2
+-#
+-# 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 2 of the License, or
+-# (at your option) any later version.
+-
+-import sys
+-
+-options = sys.argv[1]
+-searchlist = sys.argv[2]
+-
+-from aptBackend import PackageKitAptBackend
+-
+-backend = PackageKitAptBackend(sys.argv[1:])
+-backend.search_group(options,searchlist)
+-sys.exit(0)
+diff --git a/backends/apt/helpers/search-name.py b/backends/apt/helpers/search-name.py
+deleted file mode 100755
+index 9f73c89..0000000
+--- a/backends/apt/helpers/search-name.py
++++ /dev/null
+@@ -1,21 +0,0 @@
+-#!/usr/bin/python
+-#
+-# Copyright (C) 2007 Ali Sabil <ali.sabil@gmail.com>
+-#
+-# Licensed under the GNU General Public License Version 2
+-#
+-# 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 2 of the License, or
+-# (at your option) any later version.
+-
+-import sys
+-
+-options = sys.argv[1]
+-searchlist = sys.argv[2]
+-
+-from aptBackend import PackageKitAptBackend
+-
+-backend = PackageKitAptBackend(sys.argv[1:])
+-backend.search_name(options,searchlist)
+-sys.exit(0)
+diff --git a/backends/apt/packagekit b/backends/apt/packagekit
+new file mode 120000
+index 0000000..0b64032
+--- /dev/null
++++ b/backends/apt/packagekit
+@@ -0,0 +1 @@
++../../python/packagekit/
+\ No newline at end of file
+diff --git a/backends/apt/pk-apt-build-db.cpp b/backends/apt/pk-apt-build-db.cpp
+deleted file mode 100644
+index 885275d..0000000
+--- a/backends/apt/pk-apt-build-db.cpp
++++ /dev/null
+@@ -1,284 +0,0 @@
+-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+- *
+- * Copyright (C) 2007 Tom Parker <palfrey@tevp.net>
+- *
+- * Licensed under the GNU General Public License Version 2
+- *
+- * 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 2 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, write to the Free Software
+- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+- */
+-
+-//#include "pk-backend-apt.h"
+-#include <pk-backend.h>
+-#include <apt-pkg/configuration.h>
+-#include <sqlite3.h>
+-
+-typedef enum {FIELD_PKG=1,FIELD_VER,FIELD_DEPS,FIELD_ARCH,FIELD_SHORT,FIELD_LONG,FIELD_REPO} Fields;
+-
+-void apt_build_db(PkBackend * backend, sqlite3 *db)
+-{
+-      GMatchInfo *match_info;
+-      GError *error = NULL;
+-      gchar *contents = NULL;
+-      gchar *sdir;
+-      const gchar *fname;
+-      GRegex *origin, *suite;
+-      GDir *dir;
+-      GHashTable *releases;
+-      int res;
+-      sqlite3_stmt *package = NULL;
+-
+-      pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY);
+-      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+-
+-      sdir = g_build_filename(_config->Find("Dir").c_str(),_config->Find("Dir::State").c_str(),_config->Find("Dir::State::lists").c_str(), NULL);
+-      dir = g_dir_open(sdir,0,&error);
+-      if (error!=NULL)
+-      {
+-              pk_backend_error_code(backend, PK_ERROR_ENUM_INTERNAL_ERROR, "can't open %s",dir);
+-              g_error_free(error);
+-              goto search_task_cleanup;
+-      }
+-
+-      origin = g_regex_new("^Origin: (\\S+)",(GRegexCompileFlags)(G_REGEX_CASELESS|G_REGEX_OPTIMIZE|G_REGEX_MULTILINE),(GRegexMatchFlags)0,NULL);
+-      suite = g_regex_new("^Suite: (\\S+)",(GRegexCompileFlags)(G_REGEX_CASELESS|G_REGEX_OPTIMIZE|G_REGEX_MULTILINE),(GRegexMatchFlags)0,NULL);
+-
+-      releases = g_hash_table_new_full(g_str_hash,g_str_equal,g_free,g_free);
+-      while ((fname = g_dir_read_name(dir))!=NULL)
+-      {
+-              gchar *temp, *parsed_name;
+-              gchar** items = g_strsplit(fname,"_",-1);
+-              guint len = g_strv_length(items);
+-              if(len<=3) // minimum is <source>_<type>_<group>
+-              {
+-                      g_strfreev(items);
+-                      continue;
+-              }
+-
+-              /* warning: nasty hack with g_strjoinv */
+-              temp = items[len-2];
+-              items[len-2] = NULL;
+-              parsed_name = g_strjoinv("_",items);
+-              items[len-2] = temp;
+-
+-              if (g_ascii_strcasecmp(items[len-1],"Release")==0 && g_ascii_strcasecmp(items[len-2],"source")!=0)
+-              {
+-                      gchar * repo = NULL, *fullname;
+-                      fullname = g_build_filename(sdir,fname,NULL);
+-                      if (g_file_get_contents(fullname,&contents,NULL,NULL) == FALSE)
+-                      {
+-                              pk_backend_error_code(backend, PK_ERROR_ENUM_INTERNAL_ERROR, "error loading %s",fullname);
+-                              goto search_task_cleanup;
+-                      }
+-                      g_free(fullname);
+-
+-                      g_regex_match (origin, contents, (GRegexMatchFlags)0, &match_info);
+-                      if (!g_match_info_matches(match_info))
+-                      {
+-                              pk_backend_error_code(backend, PK_ERROR_ENUM_INTERNAL_ERROR, "origin regex failure in %s",fname);
+-                              goto search_task_cleanup;
+-                      }
+-                      repo = g_match_info_fetch (match_info, 1);
+-
+-                      g_regex_match (suite, contents, (GRegexMatchFlags)0, &match_info);
+-                      if (g_match_info_matches(match_info))
+-                      {
+-                              temp = g_strconcat(repo,"/",g_match_info_fetch (match_info, 1),NULL);
+-                              g_free(repo);
+-                              repo = temp;
+-                      }
+-
+-                      temp = parsed_name;
+-                      parsed_name = g_strconcat(temp,"_",items[len-2],NULL);
+-                      g_free(temp);
+-
+-                      pk_debug("type is %s, group is %s, parsed_name is %s",items[len-2],items[len-1],parsed_name);
+-
+-                      g_hash_table_insert(releases, parsed_name, repo);
+-                      g_free(contents);
+-                      contents = NULL;
+-              }
+-              else
+-                      g_free(parsed_name);
+-              g_strfreev(items);
+-      }
+-      g_dir_close(dir);
+-
+-      /* and then we need to do this again, but this time we're looking for the packages */
+-      dir = g_dir_open(sdir,0,&error);
+-      res = sqlite3_prepare_v2(db, "insert or replace into packages values (?,?,?,?,?,?,?)", -1, &package, NULL);
+-      if (res!=SQLITE_OK)
+-              pk_error("sqlite error during insert prepare: %s", sqlite3_errmsg(db));
+-      else
+-              pk_debug("insert prepare ok for %p",package);
+-      while ((fname = g_dir_read_name(dir))!=NULL)
+-      {
+-              gchar** items = g_strsplit(fname,"_",-1);
+-              guint len = g_strv_length(items);
+-              if(len<=3) // minimum is <source>_<type>_<group>
+-              {
+-                      g_strfreev(items);
+-                      continue;
+-              }
+-
+-              if (g_ascii_strcasecmp(items[len-1],"Packages")==0)
+-              {
+-                      const gchar *repo;
+-                      gchar *temp=NULL, *parsed_name=NULL;
+-                      gchar *fullname= NULL;
+-                      gchar *begin=NULL, *next=NULL, *description = NULL;
+-                      glong count = 0;
+-                      gboolean haspk = FALSE;
+-
+-                      /* warning: nasty hack with g_strjoinv */
+-                      if (g_str_has_prefix(items[len-2],"binary-"))
+-                      {
+-                              temp = items[len-3];
+-                              items[len-3] = NULL;
+-                              parsed_name = g_strjoinv("_",items);
+-                              items[len-3] = temp;
+-                      }
+-                      else
+-                      {
+-                              temp = items[len-1];
+-                              items[len-1] = NULL;
+-                              parsed_name = g_strjoinv("_",items);
+-                              items[len-1] = temp;
+-                      }
+-
+-                      pk_debug("type is %s, group is %s, parsed_name is %s",items[len-2],items[len-1],parsed_name);
+-
+-                      repo = (const gchar *)g_hash_table_lookup(releases,parsed_name);
+-                      if (repo == NULL)
+-                      {
+-                              pk_debug("Can't find repo for %s, marking as \"unknown\"",parsed_name);
+-                              repo = g_strdup("unknown");
+-                              //g_assert(0);
+-                      }
+-                      else
+-                              pk_debug("repo for %s is %s",parsed_name,repo);
+-                      g_free(parsed_name);
+-
+-                      fullname = g_build_filename(sdir,fname,NULL);
+-                      pk_debug("loading %s",fullname);
+-                      if (g_file_get_contents(fullname,&contents,NULL,NULL) == FALSE)
+-                      {
+-                              pk_backend_error_code(backend, PK_ERROR_ENUM_INTERNAL_ERROR, "error loading %s",fullname);
+-                              goto search_task_cleanup;
+-                      }
+-                      /*else
+-                              pk_debug("loaded");*/
+-
+-                      res = sqlite3_bind_text(package,FIELD_REPO,repo,-1,SQLITE_TRANSIENT);
+-                      if (res!=SQLITE_OK)
+-                              pk_error("sqlite error during repo bind: %s", sqlite3_errmsg(db));
+-                      /*else
+-                              pk_debug("repo bind ok");*/
+-
+-                      res = sqlite3_exec(db,"begin",NULL,NULL,NULL);
+-                      g_assert(res == SQLITE_OK);
+-
+-                      begin = contents;
+-
+-                      while (true)
+-                      {
+-                              next = strstr(begin,"\n");
+-                              if (next!=NULL)
+-                              {
+-                                      next[0] = '\0';
+-                                      next++;
+-                              }
+-
+-                              if (begin[0]=='\0')
+-                              {
+-                                      if (haspk)
+-                                      {
+-                                              if (description!=NULL)
+-                                              {
+-                                                      res=sqlite3_bind_text(package,FIELD_LONG,description,-1,SQLITE_TRANSIENT);
+-                                                      if (res!=SQLITE_OK)
+-                                                              pk_error("sqlite error during description bind: %s", sqlite3_errmsg(db));
+-                                                      g_free(description);
+-                                                      description = NULL;
+-                                              }
+-                                              res = sqlite3_step(package);
+-                                              if (res!=SQLITE_DONE)
+-                                                      pk_error("sqlite error during step: %s", sqlite3_errmsg(db));
+-                                              sqlite3_reset(package);
+-                                              //pk_debug("added package");
+-                                              haspk = FALSE;
+-                                      }
+-                                      //g_assert(0);
+-                              }
+-                              else if (begin[0]==' ')
+-                              {
+-                                      if (description == NULL)
+-                                              description = g_strdup(&begin[1]);
+-                                      else
+-                                      {
+-                                              gchar *oldval = description;
+-                                              description = g_strconcat(oldval, "\n",&begin[1],NULL);
+-                                              g_free(oldval);
+-                                      }
+-                              }
+-                              else
+-                              {
+-                                      gchar *colon = strchr(begin,':');
+-                                      g_assert(colon!=NULL);
+-                                      colon[0] = '\0';
+-                                      colon+=2;
+-                                      /*if (strlen(colon)>3000)
+-                                              pk_error("strlen(colon) = %d\ncolon = %s",strlen(colon),colon);*/
+-                                      //pk_debug("entry = '%s','%s'",begin,colon);
+-                                      if (begin[0] == 'P' && g_strcasecmp("Package",begin)==0)
+-                                      {
+-                                              res=sqlite3_bind_text(package,FIELD_PKG,colon,-1,SQLITE_STATIC);
+-                                              haspk = TRUE;
+-                                              count++;
+-                                              if (count%1000==0)
+-                                                      pk_debug("Package %ld (%s)",count,colon);
+-                                      }
+-                                      else if (begin[0] == 'V' && g_strcasecmp("Version",begin)==0)
+-                                              res=sqlite3_bind_text(package,FIELD_VER,colon,-1,SQLITE_STATIC);
+-                                      else if (begin[0] == 'D' && g_strcasecmp("Depends",begin)==0)
+-                                              res=sqlite3_bind_text(package,FIELD_DEPS,colon,-1,SQLITE_STATIC);
+-                                      else if (begin[0] == 'A' && g_strcasecmp("Architecture",begin)==0)
+-                                              res=sqlite3_bind_text(package,FIELD_ARCH,colon,-1,SQLITE_STATIC);
+-                                      else if (begin[0] == 'D' && g_strcasecmp("Description",begin)==0)
+-                                              res=sqlite3_bind_text(package,FIELD_SHORT,colon,-1,SQLITE_STATIC);
+-                                      if (res!=SQLITE_OK)
+-                                              pk_error("sqlite error during %s bind: %s", begin, sqlite3_errmsg(db));
+-                              }
+-                              if (next == NULL)
+-                                      break;
+-                              begin = next;
+-                      }
+-                      res = sqlite3_exec(db,"commit",NULL,NULL,NULL);
+-                      if (res!=SQLITE_OK)
+-                              pk_error("sqlite error during commit: %s", sqlite3_errmsg(db));
+-                      res = sqlite3_clear_bindings(package);
+-                      if (res!=SQLITE_OK)
+-                              pk_error("sqlite error during clear: %s", sqlite3_errmsg(db));
+-                      g_free(contents);
+-                      contents = NULL;
+-              }
+-      }
+-      sqlite3_finalize(package);
+-
+-search_task_cleanup:
+-      g_dir_close(dir);
+-      g_free(sdir);
+-      g_free(contents);
+-}
+-
+diff --git a/backends/apt/pk-apt-build-db.h b/backends/apt/pk-apt-build-db.h
+deleted file mode 100644
+index bb786a9..0000000
+--- a/backends/apt/pk-apt-build-db.h
++++ /dev/null
+@@ -1,30 +0,0 @@
+-#ifndef PK_APT_BUILD_DB
+-#define PK_APT_BUILD_DB
+-
+-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+- *
+- * Copyright (C) 2007 Tom Parker <palfrey@tevp.net>
+- *
+- * Licensed under the GNU General Public License Version 2
+- *
+- * 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 2 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, write to the Free Software
+- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+- */
+-
+-#include <sqlite3.h>
+-#include <pk-backend.h>
+-
+-void apt_build_db(PkBackend * backend, sqlite3 *db);
+-
+-#endif
+diff --git a/backends/apt/pk-apt-search-plain.c b/backends/apt/pk-apt-search-plain.c
+deleted file mode 100644
+index 5e5b4e5..0000000
+--- a/backends/apt/pk-apt-search-plain.c
++++ /dev/null
+@@ -1,106 +0,0 @@
+-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+- *
+- * Copyright (C) 2007 Ali Sabil <ali.sabil@gmail.com>
+- *
+- * Licensed under the GNU General Public License Version 2
+- *
+- * 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 2 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, write to the Free Software
+- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+- */
+-
+-#include <gmodule.h>
+-#include <glib.h>
+-#include <string.h>
+-#include <pk-backend.h>
+-#include <pk-backend-spawn.h>
+-
+-extern PkBackendSpawn *spawn;
+-
+-/**
+- * backend_get_groups:
+- */
+-static PkGroupEnum
+-backend_get_groups (PkBackend *backend)
+-{
+-      return (PK_GROUP_ENUM_ACCESSORIES |
+-              PK_GROUP_ENUM_GAMES |
+-              PK_GROUP_ENUM_GRAPHICS |
+-              PK_GROUP_ENUM_INTERNET |
+-              PK_GROUP_ENUM_OFFICE |
+-              PK_GROUP_ENUM_OTHER |
+-              PK_GROUP_ENUM_PROGRAMMING |
+-              PK_GROUP_ENUM_MULTIMEDIA |
+-              PK_GROUP_ENUM_SYSTEM);
+-}
+-
+-/**
+- * backend_get_filters:
+- */
+-static PkFilterEnum
+-backend_get_filters (PkBackend *backend)
+-{
+-      return (PK_FILTER_ENUM_GUI |
+-              PK_FILTER_ENUM_INSTALLED |
+-              PK_FILTER_ENUM_DEVELOPMENT);
+-}
+-
+-/**
+- * backend_get_details:
+- */
+-
+-void
+-backend_get_details (PkBackend *backend, const gchar *package_id)
+-{
+-      pk_backend_spawn_helper (spawn, "get-details.py", package_id, NULL);
+-}
+-
+-/**
+- * backend_search_details:
+- */
+-
+-void
+-backend_search_details (PkBackend *backend, PkFilterEnum filters, const gchar *search)
+-{
+-      gchar *filters_text;
+-      filters_text = pk_filter_enums_to_text (filters);
+-      pk_backend_spawn_helper (spawn, "search-details.py", filters_texts_text, search, NULL);
+-      g_free (filters_text);
+-}
+-
+-/**
+- * backend_search_name:
+- */
+-void
+-backend_search_name (PkBackend *backend, PkFilterEnum filters, const gchar *search)
+-{
+-      gchar *filters_text;
+-      filters_text = pk_filter_enums_to_text (filters);
+-      pk_backend_spawn_helper (spawn, "search-name.py", filters_text, search, NULL);
+-      g_free (filters_text);
+-}
+-
+-/**
+- * backend_search_group:
+- */
+-void
+-backend_search_group (PkBackend *backend, PkFilterEnum filters, const gchar *search)
+-{
+-      gchar *filters_text;
+-      pk_backend_spawn_helper (spawn, "search-group.py", filters_text, search, NULL);
+-      g_free (filters_text);
+-}
+-
+-/* don't need to do any setup/finalize in the plain search mode */
+-void backend_init_search(PkBackend *backend) {}
+-void backend_finish_search(PkBackend *backend) {}
+diff --git a/backends/apt/pk-apt-search-sqlite.cpp b/backends/apt/pk-apt-search-sqlite.cpp
+deleted file mode 100644
+index 98bdc7f..0000000
+--- a/backends/apt/pk-apt-search-sqlite.cpp
++++ /dev/null
+@@ -1,135 +0,0 @@
+-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+- *
+- * Copyright (C) 2007 Ali Sabil <ali.sabil@gmail.com>
+- *
+- * Licensed under the GNU General Public License Version 2
+- *
+- * 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 2 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, write to the Free Software
+- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+- */
+-
+-#include <gmodule.h>
+-#include <glib.h>
+-#include <string.h>
+-#include <pk-backend.h>
+-#include <pk-backend-spawn.h>
+-#include "pk-sqlite-pkg-cache.h"
+-#include <apt-pkg/configuration.h>
+-#include <apt-pkg/init.h>
+-#include "pk-apt-build-db.h"
+-
+-static PkBackendSpawn *spawn;
+-
+-/**
+- * backend_get_groups:
+- */
+-extern "C" PkGroupEnum
+-backend_get_groups (PkBackend *backend)
+-{
+-      return (PK_GROUP_ENUM_ACCESSORIES |
+-              PK_GROUP_ENUM_GAMES |
+-              PK_GROUP_ENUM_GRAPHICS |
+-              PK_GROUP_ENUM_INTERNET |
+-              PK_GROUP_ENUM_OFFICE |
+-              PK_GROUP_ENUM_OTHER |
+-              PK_GROUP_ENUM_PROGRAMMING |
+-              PK_GROUP_ENUM_MULTIMEDIA |
+-              PK_GROUP_ENUM_SYSTEM);
+-}
+-
+-/**
+- * backend_get_filters:
+- */
+-extern "C" PkFilterEnum
+-backend_get_filters (PkBackend *backend)
+-{
+-      return (PK_FILTER_ENUM_GUI |
+-              PK_FILTER_ENUM_INSTALLED |
+-              PK_FILTER_ENUM_DEVELOPMENT);
+-}
+-
+-/**
+- * backend_get_details:
+- */
+-
+-extern "C" void
+-backend_get_details (PkBackend *backend, const gchar *package_id)
+-{
+-      sqlite_get_details(backend,package_id);
+-}
+-
+-/**
+- * backend_search_details:
+- */
+-
+-extern "C" void
+-backend_search_details (PkBackend *backend, const gchar *filter, const gchar *search)
+-{
+-      sqlite_search_details(backend,filter,search);
+-}
+-
+-/**
+- * backend_search_name:
+- */
+-extern "C" void
+-backend_search_name (PkBackend *backend, const gchar *filter, const gchar *search)
+-{
+-      sqlite_search_name(backend,filter,search);
+-}
+-
+-/**
+- * backend_search_group:
+- */
+-extern "C" void
+-backend_search_group (PkBackend *backend, const gchar *filter, const gchar *search)
+-{
+-      pk_backend_set_allow_cancel (backend, TRUE);
+-      pk_backend_spawn_helper (spawn, "search-group.py", filter, search, NULL);
+-}
+-
+-static gboolean inited = FALSE;
+-
+-#define APT_DB PK_DB_DIR "/apt.db"
+-
+-extern "C" void backend_init_search(PkBackend *backend)
+-{
+-      if (!inited)
+-      {
+-              gchar *apt_fname = NULL;
+-              if (pkgInitConfig(*_config) == false)
+-                      pk_debug("pkginitconfig was false");
+-              if (pkgInitSystem(*_config, _system) == false)
+-                      pk_debug("pkginitsystem was false");
+-
+-              apt_fname = g_strconcat(
+-                              _config->Find("Dir").c_str(),
+-                              _config->Find("Dir::Cache").c_str(),
+-                              _config->Find("Dir::Cache::pkgcache").c_str(),
+-                              NULL);
+-
+-              //sqlite_set_installed_check(is_installed);
+-              sqlite_init_cache(backend, APT_DB, apt_fname, apt_build_db);
+-              g_free(apt_fname);
+-
+-              spawn = pk_backend_spawn_new ();
+-              pk_backend_spawn_set_name (spawn, "apt-sqlite");
+-
+-              inited = TRUE;
+-      }
+-}
+-
+-extern "C" void backend_finish_search(PkBackend *backend)
+-{
+-      sqlite_finish_cache(backend);
+-}
+diff --git a/backends/apt/pk-apt-search.h b/backends/apt/pk-apt-search.h
+deleted file mode 100644
+index e36e89f..0000000
+--- a/backends/apt/pk-apt-search.h
++++ /dev/null
+@@ -1,36 +0,0 @@
+-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+- *
+- * Copyright (C) 2007 Tom Parker <palfrey@tevp.net>
+- *
+- * Licensed under the GNU General Public License Version 2
+- *
+- * 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 2 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, write to the Free Software
+- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+- */
+-
+-#ifndef __PK_APT_SEARCH_H
+-#define __PK_APT_SEARCH_H
+-
+-#include <glib.h>
+-#include <pk-backend.h>
+-
+-void backend_init_search(PkBackend *backend);
+-void backend_finish_search(PkBackend *backend);
+-
+-void backend_get_details (PkBackend *backend, const gchar *package_id);
+-void backend_search_details (PkBackend *backend, const gchar *filter, const gchar *search);
+-void backend_search_name (PkBackend *backend, const gchar *filter, const gchar *search);
+-void backend_search_group (PkBackend *backend, const gchar *filter, const gchar *search);
+-
+-#endif
+diff --git a/backends/apt/pk-backend-apt.c b/backends/apt/pk-backend-apt.c
+index f59cd88..70836b2 100644
+--- a/backends/apt/pk-backend-apt.c
++++ b/backends/apt/pk-backend-apt.c
+@@ -20,16 +20,12 @@
+  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+  */
+-#include <gmodule.h>
+-#include <glib.h>
+-#include <string.h>
+ #include <pk-backend.h>
+-#include <pk-backend-spawn.h>
+-#include <pk-package-ids.h>
+-#include "pk-apt-search.h"
+-#include "config.h"
++#include <pk-backend-dbus.h>
+-PkBackendSpawn *spawn;
++static PkBackendDbus *dbus;
++
++#define PK_DBUS_BACKEND_SERVICE_APT   "org.freedesktop.PackageKitAptBackend"
+ /**
+  * backend_initialize:
+@@ -39,9 +35,8 @@ static void
+ backend_initialize (PkBackend *backend)
+ {
+       pk_debug ("FILTER: initialize");
+-      spawn = pk_backend_spawn_new ();
+-      pk_backend_spawn_set_name (spawn, "apt");
+-      backend_init_search (backend);
++      dbus = pk_backend_dbus_new ();
++      pk_backend_dbus_set_name (dbus, PK_DBUS_BACKEND_SERVICE_APT);
+ }
+ /**
+@@ -52,8 +47,8 @@ static void
+ backend_destroy (PkBackend *backend)
+ {
+       pk_debug ("FILTER: destroy");
+-      backend_finish_search (backend);
+-      g_object_unref (spawn);
++      pk_backend_dbus_kill (dbus);
++      g_object_unref (dbus);
+ }
+ /**
+@@ -85,184 +80,144 @@ backend_get_filters (PkBackend *backend)
+ }
+ /**
+- * pk_backend_bool_to_text:
++ * backend_get_updates:
+  */
+-static const gchar *
+-pk_backend_bool_to_text (gboolean value)
++static void
++backend_get_updates (PkBackend *backend, PkFilterEnum filters)
+ {
+-      if (value == TRUE) {
+-              return "yes";
+-      }
+-      return "no";
++      pk_backend_dbus_get_updates (dbus, filters);
+ }
+ /**
+- * backend_get_depends:
+- */
++ * backend_refresh_cache:
++ * */
+ static void
+-backend_get_depends (PkBackend *backend, PkFilterEnum filters, const gchar *package_id, gboolean recursive)
++backend_refresh_cache (PkBackend *backend, gboolean force)
+ {
+-      gchar *filters_text;
+-      filters_text = pk_filter_enums_to_text (filters);
+-      pk_backend_spawn_helper (spawn, "get-depends.py", filters_text, package_id, pk_backend_bool_to_text (recursive), NULL);
+-      g_free (filters_text);
++      // check network state
++      if (!pk_backend_is_online (backend)) {
++              pk_backend_error_code (backend, PK_ERROR_ENUM_NO_NETWORK, "Cannot refresh cache whilst offline");
++              pk_backend_finished (backend);
++              return;
++      }
++
++      pk_backend_dbus_refresh_cache(dbus, force);
+ }
+ /**
+- * backend_get_updates:
+- */
++ * pk_backend_update_system:
++ * */
+ static void
+-backend_get_updates (PkBackend *backend, PkFilterEnum filters)
++backend_update_system (PkBackend *backend)
+ {
+-      gchar *filters_text;
+-      filters_text = pk_filter_enums_to_text (filters);
+-      pk_backend_spawn_helper (spawn, "get-updates.py", filters_text, NULL);
+-      g_free (filters_text);
++      pk_backend_dbus_update_system (dbus);
+ }
+ /**
+- * backend_get_update_detail:
+- */
++ * backend_install_packages
++ *  */
+ static void
+-backend_get_update_detail (PkBackend *backend, const gchar *package_id)
++backend_install_packages (PkBackend *backend, gchar **package_ids)
+ {
+-      pk_backend_spawn_helper (spawn, "get-update-detail.py", package_id, NULL);
++      pk_backend_dbus_install_packages (dbus, package_ids);
+ }
+ /**
+- * backend_install_packages:
+- */
++ * backend_remove_packages
++ *  */
+ static void
+-backend_install_packages (PkBackend *backend, gchar **package_ids)
++backend_remove_packages (PkBackend *backend, gchar **package_ids, gboolean allow_deps, gboolean autoremove)
+ {
+-      gchar *package_ids_temp;
+-
+-      /* check network state */
+-      if (!pk_backend_is_online (backend)) {
+-              pk_backend_error_code (backend, PK_ERROR_ENUM_NO_NETWORK, "Cannot install when offline");
+-              pk_backend_finished (backend);
+-              return;
+-      }
+-
+-      /* send the complete list as stdin */
+-      package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+-      pk_backend_spawn_helper (spawn, "install-packages.py", package_ids_temp, NULL);
+-      g_free (package_ids_temp);
++      pk_backend_dbus_remove_packages (dbus, package_ids, allow_deps, autoremove);
+ }
+ /**
+- * backend_refresh_cache:
+- */
++ * backend_get_details:
++ *  */
+ static void
+-backend_refresh_cache (PkBackend *backend, gboolean force)
++backend_get_details (PkBackend *backend, const gchar *package_id)
+ {
+-      /* check network state */
+-      if (!pk_backend_is_online (backend)) {
+-              pk_backend_error_code (backend, PK_ERROR_ENUM_NO_NETWORK, "Cannot refresh cache whilst offline");
+-              pk_backend_finished (backend);
+-              return;
+-      }
+-
+-      pk_backend_spawn_helper (spawn, "refresh-cache.py", NULL);
++      pk_backend_dbus_get_details (dbus, package_id);
+ }
+ /**
+- * pk_backend_remove_packages:
+- * 
++ *  * pk_backend_search_details:
++ *   */
+ static void
+-backend_remove_packages (PkBackend *backend, gchar **package_ids, gboolean allow_deps, gboolean autoremove)
++backend_search_details (PkBackend *backend, PkFilterEnum filters, const gchar *search)
+ {
+-      gchar *package_ids_temp;
+-      package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+-      pk_backend_spawn_helper (spawn, "remove-packages.py", pk_backend_bool_to_text (allow_deps), package_ids_temp, NULL);
+-      g_free (package_ids_temp);
+-} */
++      pk_backend_dbus_search_details (dbus, filters, search);
++}
+ /**
+- * pk_backend_update_packages:
+- */
++ *  * pk_backend_search_name:
++ *   */
+ static void
+-backend_update_packages (PkBackend *backend, gchar **package_ids)
++backend_search_name (PkBackend *backend, PkFilterEnum filters, const gchar *search)
+ {
+-      gchar *package_ids_temp;
+-
+-      /* check network state */
+-      if (!pk_backend_is_online (backend)) {
+-              pk_backend_error_code (backend, PK_ERROR_ENUM_NO_NETWORK, "Cannot install when offline");
+-              pk_backend_finished (backend);
+-              return;
+-      }
+-
+-      /* send the complete list as stdin */
+-      package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+-      pk_backend_spawn_helper (spawn, "update-packages.py", package_ids_temp, NULL);
+-      g_free (package_ids_temp);
++      pk_backend_dbus_search_name (dbus, filters, search);
+ }
+ /**
+- * pk_backend_update_system:
+- */
++ *  * pk_backend_cancel:
++ *   */
+ static void
+-backend_update_system (PkBackend *backend)
++backend_cancel (PkBackend *backend)
+ {
+-      pk_backend_spawn_helper (spawn, "update-system.py", NULL);
++      pk_backend_dbus_cancel (dbus);
+ }
+ /**
+- * pk_backend_resolve:
+- */
++ *  * pk_backend_resolve:
++ *   */
+ static void
+ backend_resolve (PkBackend *backend, PkFilterEnum filters, const gchar *package_id)
+ {
+-      gchar *filters_text;
+-      filters_text = pk_filter_enums_to_text (filters);
+-      pk_backend_spawn_helper (spawn, "resolve.py", filters_text, package_id, NULL);
+-      g_free (filters_text);
++              pk_backend_dbus_resolve (dbus, filters, package_id);
+ }
+ /**
+- * pk_backend_get_repo_list:
+- */
++ *  * pk_backend_get_packages:
++ *   */
+ static void
+-backend_get_repo_list (PkBackend *backend, PkFilterEnum filters)
++backend_get_packages (PkBackend *backend, PkFilterEnum filters)
+ {
+-      gchar *filters_text;
+-      filters_text = pk_filter_enums_to_text (filters);
+-      pk_backend_spawn_helper (spawn, "get-repo-list.py", filters_text, NULL);
+-      g_free (filters_text);
++              pk_backend_dbus_get_packages (dbus, filters);
+ }
++
++
+ PK_BACKEND_OPTIONS (
+-      "Apt (with " APT_SEARCH " searching)",                          /* description */
+-      "Ali Sabil <ali.sabil@gmail.com>; Tom Parker <palfrey@tevp.net>",       /* author */
++      "Apt",                                  /* description */
++      "Ali Sabil <ali.sabil@gmail.com>; Tom Parker <palfrey@tevp.net>; Sebastian Heinlein <glatzor@ubuntu.com>",      /* author */
+       backend_initialize,                     /* initalize */
+       backend_destroy,                        /* destroy */
+       backend_get_groups,                     /* get_groups */
+       backend_get_filters,                    /* get_filters */
+-      NULL,                                   /* cancel */
+-      backend_get_depends,                    /* get_depends */
++      backend_cancel,                         /* cancel */
++      NULL,                                   /* get_depends */
+       backend_get_details,                    /* get_details */
+       NULL,                                   /* get_files */
+-      NULL,                                   /* get_packages */
+-      backend_get_repo_list,                  /* get_repo_list */
++      backend_get_packages,                   /* get_packages */
++      NULL,                                   /* get_repo_list */
+       NULL,                                   /* get_requires */
+-      backend_get_update_detail,              /* get_update_detail */
++      NULL,                                   /* get_update_detail */
+       backend_get_updates,                    /* get_updates */
+       NULL,                                   /* install_files */
+       backend_install_packages,               /* install_packages */
+       NULL,                                   /* install_signature */
+       backend_refresh_cache,                  /* refresh_cache */
+-      NULL,                                   /* remove_packages */
++      backend_remove_packages,                /* remove_packages */
+       NULL,                                   /* repo_enable */
+       NULL,                                   /* repo_set_data */
+       backend_resolve,                        /* resolve */
+       NULL,                                   /* rollback */
+       backend_search_details,                 /* search_details */
+       NULL,                                   /* search_file */
+-      backend_search_group,                   /* search_group */
++      NULL,                                   /* search_group */
+       backend_search_name,                    /* search_name */
+       NULL,                                   /* service_pack */
+-      backend_update_package,                 /* update_package */
++      NULL,                                   /* update_packages */
+       backend_update_system,                  /* update_system */
+       NULL                                    /* what_provides */
+ );
+diff --git a/backends/apt/pk-sqlite-pkg-cache.cpp b/backends/apt/pk-sqlite-pkg-cache.cpp
+deleted file mode 100644
+index 1bf9a50..0000000
+--- a/backends/apt/pk-sqlite-pkg-cache.cpp
++++ /dev/null
+@@ -1,215 +0,0 @@
+-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+- *
+- * Copyright (C) 2007 Tom Parker <palfrey@tevp.net>
+- *
+- * Licensed under the GNU General Public License Version 2
+- *
+- * 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 2 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, write to the Free Software
+- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+- */
+-
+-#include <glib.h>
+-#include <glib/gstdio.h>
+-#include "pk-sqlite-pkg-cache.h"
+-
+-static sqlite3 *db = NULL;
+-static PkBackend *backend;
+-static gboolean(*is_installed) (const PkPackageId *) = NULL;
+-
+-void sqlite_set_installed_check(gboolean(*func) (const PkPackageId *))
+-{
+-      is_installed = func;
+-}
+-
+-void
+-sqlite_init_cache(PkBackend *backend, const char* dbname, const char *compare_fname, void (*build_db)(PkBackend *, sqlite3 *))
+-{
+-      int ret;
+-      struct stat st;
+-      time_t db_age;
+-
+-      ret = sqlite3_open (dbname, &db);
+-      g_assert(ret == SQLITE_OK);
+-      g_assert(db!=NULL);
+-      ret = sqlite3_exec(db,"PRAGMA synchronous = OFF",NULL,NULL,NULL);
+-      g_assert(ret == SQLITE_OK);
+-
+-      g_stat(dbname, &st);
+-      db_age = st.st_mtime;
+-      g_stat(compare_fname, &st);
+-      if (db_age>=st.st_mtime)
+-      {
+-              ret = sqlite3_exec(db, "select value from params where name = 'build_complete'", NULL, NULL, NULL);
+-              if (ret != SQLITE_ERROR)
+-                      return;
+-              pk_debug("ages are %lu for db, and %lu for comparism",db_age,st.st_mtime);
+-      }
+-      ret = sqlite3_exec(db,"drop table packages",NULL,NULL,NULL); // wipe it!
+-      //g_assert(ret == SQLITE_OK);
+-      pk_debug("wiped db");
+-      ret = sqlite3_exec(db,"create table packages (name text, version text, deps text, arch text, short_desc text, long_desc text, repo string, primary key(name,version,arch,repo))",NULL,NULL,NULL);
+-      g_assert(ret == SQLITE_OK);
+-
+-      build_db(backend,db);
+-
+-      sqlite3_exec(db,"create table params (name text primary key, value integer)", NULL, NULL, NULL);
+-      sqlite3_exec(db,"insert into params values ('build_complete',1)", NULL, NULL, NULL);
+-}
+-
+-void sqlite_finish_cache(PkBackend *backend)
+-{
+-      sqlite3_close(db);
+-}
+-
+-// sqlite_search_packages_thread
+-static gboolean
+-sqlite_search_packages_thread (PkBackend *backend)
+-{
+-      int res;
+-      gchar *sel;
+-      const gchar *search;
+-
+-      pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY);
+-      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+-      type = pk_backend_get_uint (backend, "type");
+-      search = pk_backend_get_string (backend, "search");
+-
+-      pk_debug("finding %s", search);
+-
+-      sqlite3_stmt *package = NULL;
+-      g_strdelimit(search," ",'%');
+-
+-      if (type == SEARCH_NAME)
+-              sel = g_strdup_printf("select name,version,arch,repo,short_desc from packages where name like '%%%s%%'",search);
+-      else if (type == SEARCH_DETAILS)
+-              sel = g_strdup_printf("select name,version,arch,repo,short_desc from packages where name like '%%%s%%' or short_desc like '%%%s%%' or long_desc like '%%%s%%'",search, search, search);
+-      else
+-      {
+-              pk_backend_error_code(backend, PK_ERROR_ENUM_INTERNAL_ERROR, "Unknown search task type");
+-              goto end_search_packages;
+-      }
+-
+-      pk_debug("statement is '%s'",sel);
+-      res = sqlite3_prepare_v2(db,sel, -1, &package, NULL);
+-      g_free(sel);
+-      if (res!=SQLITE_OK)
+-              pk_error("sqlite error during select prepare: %s", sqlite3_errmsg(db));
+-      res = sqlite3_step(package);
+-      while (res == SQLITE_ROW)
+-      {
+-              PkPackageId *pid = pk_package_id_new_from_list((const gchar*)sqlite3_column_text(package,0),
+-                              (const gchar*)sqlite3_column_text(package,1),
+-                              (const gchar*)sqlite3_column_text(package,2),
+-                              (const gchar*)sqlite3_column_text(package,3));
+-
+-              gchar *cpid = pk_package_id_to_string(pid);
+-              PkInfoEnum pie = PK_INFO_ENUM_UNKNOWN;
+-
+-              if (is_installed != NULL)
+-                      pie = is_installed(pid)?PK_INFO_ENUM_INSTALLED:PK_INFO_ENUM_AVAILABLE;
+-
+-              pk_backend_package(backend, pie, cpid, (const gchar*)sqlite3_column_text(package,4));
+-
+-              g_free(cpid);
+-              pk_package_id_free(pid);
+-
+-              if (res==SQLITE_ROW)
+-                      res = sqlite3_step(package);
+-      }
+-      if (res!=SQLITE_DONE)
+-      {
+-              pk_debug("sqlite error during step (%d): %s", res, sqlite3_errmsg(db));
+-              g_assert(0);
+-      }
+-
+-end_search_packages:
+-      pk_backend_finished (backend);
+-      return TRUE;
+-}
+-
+-/**
+- * sqlite_search_details:
+- */
+-void
+-sqlite_search_details (PkBackend *backend, const gchar *filter, const gchar *search)
+-{
+-      pk_backend_set_uint (backend, "type", SEARCH_DETAILS);
+-      pk_backend_thread_create (backend, sqlite_search_packages_thread);
+-}
+-
+-/**
+- * sqlite_search_name:
+- */
+-void
+-sqlite_search_name (PkBackend *backend, const gchar *filter, const gchar *search)
+-{
+-      pk_backend_set_uint (backend, "type", SEARCH_NAME);
+-      pk_backend_thread_create (backend, sqlite_search_packages_thread);
+-}
+-
+-// sqlite_get_details_thread
+-static gboolean
+-sqlite_get_details_thread (PkBackend *backend)
+-{
+-      PkPackageId *pi;
+-      const gchar *package_id;
+-      int res;
+-
+-      package_id = pk_backend_get_string (backend, "package_id");
+-      pi = pk_package_id_new_from_string(package_id);
+-      if (pi == NULL)
+-      {
+-              pk_backend_error_code(backend, PK_ERROR_ENUM_PACKAGE_ID_INVALID, "invalid package id");
+-              pk_backend_finished(backend);
+-              return;
+-      }
+-
+-      pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY);
+-      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+-
+-      pk_debug("finding %s", pi->name);
+-
+-      sqlite3_stmt *package = NULL;
+-      gchar *sel = g_strdup_printf("select long_desc from packages where name = '%s' and version = '%s' and repo = '%s'",pi->name,pi->version,pi->data);
+-      pk_debug("statement is '%s'",sel);
+-      res = sqlite3_prepare_v2(db,sel, -1, &package, NULL);
+-      g_free(sel);
+-      if (res!=SQLITE_OK)
+-              pk_error("sqlite error during select prepare: %s", sqlite3_errmsg(db));
+-      res = sqlite3_step(package);
+-      pk_backend_details(backend,pi->name, "unknown", PK_GROUP_ENUM_OTHER,(const gchar*)sqlite3_column_text(package,0),"",0);
+-      res = sqlite3_step(package);
+-      if (res==SQLITE_ROW)
+-              pk_error("multiple matches for that package!");
+-      if (res!=SQLITE_DONE)
+-      {
+-              pk_debug("sqlite error during step (%d): %s", res, sqlite3_errmsg(db));
+-              g_assert(0);
+-      }
+-
+-      g_free(dt);
+-
+-      return TRUE;
+-}
+-
+-/**
+- * sqlite_get_details:
+- */
+-extern "C++" void
+-sqlite_get_details (PkBackend *backend, const gchar *package_id)
+-{
+-      pk_backend_thread_create (backend, sqlite_get_details_thread);
+-      return;
+-}
+-
+diff --git a/backends/apt/pk-sqlite-pkg-cache.h b/backends/apt/pk-sqlite-pkg-cache.h
+deleted file mode 100644
+index 68fad42..0000000
+--- a/backends/apt/pk-sqlite-pkg-cache.h
++++ /dev/null
+@@ -1,42 +0,0 @@
+-#ifndef SQLITE_PKT_CACHE
+-#define SQLITE_PKT_CACHE
+-
+-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+- *
+- * Copyright (C) 2007 Tom Parker <palfrey@tevp.net>
+- *
+- * Licensed under the GNU General Public License Version 2
+- *
+- * 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 2 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, write to the Free Software
+- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+- */
+-
+-typedef enum {
+-      SEARCH_NAME = 1,
+-      SEARCH_DETAILS,
+-      SEARCH_FILE
+-} SearchDepth;
+-
+-#include <pk-backend.h>
+-#include <sqlite3.h>
+-
+-void sqlite_init_cache(PkBackend *backend, const char* dbname, const char* compare_fname, void (*build_db)(PkBackend *, sqlite3 *db));
+-void sqlite_finish_cache(PkBackend *backend);
+-
+-void sqlite_search_details (PkBackend *backend, const gchar *filter, const gchar *search);
+-void sqlite_search_name (PkBackend *backend, const gchar *filter, const gchar *search);
+-void backend_search_common(PkBackend * backend, const gchar * filter, const gchar * search, SearchDepth which, PkBackendThreadFunc func);
+-void sqlite_get_details (PkBackend *backend, const gchar *package_id);
+-
+-#endif
+diff --git a/backends/apt/profiler.py b/backends/apt/profiler.py
+new file mode 100644
+index 0000000..1b5d30f
+--- /dev/null
++++ b/backends/apt/profiler.py
+@@ -0,0 +1,40 @@
++#!/usr/bin/env python
++# Licensed under the GNU General Public License Version 2
++#
++# 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 2 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, write to the Free Software
++# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++# Copyright (C) 2008
++#    Sebastian Heinlein <sebi@glatzor.de>
++
++"""
++Allows to start the apt2 backend in a profling mode
++"""
++
++__author__ = "Sebastian Heinlein <devel@glatzor.de>"
++
++
++import hotshot
++import sys
++
++from aptDBUSBackend import main
++
++if len(sys.argv) == 2:
++    profile = sys.argv[1]
++else:
++    profile = "profile"
++
++prof = hotshot.Profile(profile)
++print prof.runcall(main)
++prof.close()
+diff --git a/backends/apt/test.py b/backends/apt/test.py
+new file mode 100755
+index 0000000..a1d5ffb
+--- /dev/null
++++ b/backends/apt/test.py
+@@ -0,0 +1,98 @@
++#!/usr/bin/python
++# Licensed under the GNU General Public License Version 2
++#
++# 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 2 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, write to the Free Software
++# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++# Copyright (C) 2007
++#    Tim Lauridsen <timlau@fedoraproject.org>
++
++import sys
++import dbus
++from packagekit.enums import *
++
++PACKAGEKIT_DBUS_SERVICE = 'org.freedesktop.PackageKitAptBackend'
++PACKAGEKIT_DBUS_INTERFACE = 'org.freedesktop.PackageKitBackend'
++PACKAGEKIT_DBUS_PATH = '/org/freedesktop/PackageKitBackend'
++PKG_ID = 'xterm;232-1;i386;Debian'
++
++try:
++    bus = dbus.SystemBus()
++except dbus.DBusException, e:
++    print  "Unable to connect to dbus"
++    print "%s" %(e,)
++    sys.exit(1)
++
++try:
++    proxy = bus.get_object(PACKAGEKIT_DBUS_SERVICE, PACKAGEKIT_DBUS_PATH)
++    iface = dbus.Interface(proxy, PACKAGEKIT_DBUS_INTERFACE)
++    cmd = sys.argv[1]
++    if cmd == 'init' or cmd == 'all':
++        print "Testing Init()"
++        iface.Init()
++    if cmd == 'cancel':
++        print "Canceling"
++        iface.Cancel()
++    if cmd == 'get-updates' or cmd == 'all':
++        print "Testing GetUpdate()"
++        iface.GetUpdates()
++    if cmd == 'search-name' or cmd == 'all':
++        print "Testing SearchName(FILTER_NONE,'apt')"
++        iface.SearchName(FILTER_NONE,'apt')
++    if cmd == 'search-details' or cmd == 'all':
++        print "SearchDetails(FILTER_NONE,'dbus')"
++        iface.SearchDetails(FILTER_NONE,'dbus')
++    if cmd == 'search-group' or cmd == 'all':
++        print "Testing SearchGroup(FILTER_NONE,GROUP_GAMES)"
++        iface.SearchGroup(FILTER_NONE,GROUP_GAMES)
++    if cmd == 'search-file' or cmd == 'all':
++        print "Testing SearchFile(FILTER_NONE,'/usr/bin/yum')"
++        iface.SearchFile(FILTER_NONE,'/usr/bin/yum')
++    if cmd == 'get-requires' or cmd == 'all':
++        print "Testing GetRequires(PKG_ID,False)"
++        iface.GetRequires(PKG_ID,False)
++    if cmd == 'get-depends' or cmd == 'all':
++        print "Testing GetDepends(PKG_ID,False)"
++        iface.GetDepends(PKG_ID,False)
++    if cmd == 'refresh-cache' or cmd == 'all':
++        print "Testing RefreshCache()"
++        iface.RefreshCache()
++    if cmd == 'resolve' or cmd == 'all':
++        print "Testing Resolve(FILTER_NONE,'yum')"
++        iface.Resolve(FILTER_NONE,'yum')
++    if cmd == 'get-details' or cmd == 'all':
++        print "Testing GetDetails(PKG_ID)"
++        iface.GetDetails(PKG_ID)
++    if cmd == 'get-files' or cmd == 'all':
++        print "Testing GetFiles(PKG_ID)"
++        iface.GetFiles(PKG_ID)
++    if cmd == 'get-packages' or cmd == 'all':
++        print "Testing GetPackages(FILTER_INSTALLED,'no')"
++        iface.GetPackages(FILTER_INSTALLED,'no')
++    if cmd == 'get-repolist' or cmd == 'all':
++        print "Testing GetRepoList()"
++        iface.GetRepoList()
++    if cmd == 'get-updatedetail' or cmd == 'all':
++        print "Testing GetUpdateDetail(PKG_ID)"
++        iface.GetUpdateDetail(PKG_ID)
++    #print "Testing "
++    #iface.
++    if cmd == 'exit' or cmd == 'all':
++        print "Testing Exit()"
++        iface.Exit()
++    
++except dbus.DBusException, e:
++    print "Unable to send message on dbus"
++    print "%s" %(e,)
++    sys.exit(1)
+diff --git a/backends/apt2/.gitignore b/backends/apt2/.gitignore
+deleted file mode 100644
+index c851833..0000000
+--- a/backends/apt2/.gitignore
++++ /dev/null
+@@ -1,10 +0,0 @@
+-.deps
+-.libs
+-Makefile
+-Makefile.in
+-*.la
+-*.lo
+-*.loT
+-*.o
+-*~
+-
+diff --git a/backends/apt2/HACKING b/backends/apt2/HACKING
+deleted file mode 100644
+index 2b99c5d..0000000
+--- a/backends/apt2/HACKING
++++ /dev/null
+@@ -1,5 +0,0 @@
+-The backend can be tested by running it as root from the source code
+-repository. Make sure to kill packagekitd before to force a reintializing
+-of the cache:
+-
+-  killall packagekitd; python aptDBUSBackend.py 
+diff --git a/backends/apt2/Makefile.am b/backends/apt2/Makefile.am
+deleted file mode 100644
+index 91c0c46..0000000
+--- a/backends/apt2/Makefile.am
++++ /dev/null
+@@ -1,25 +0,0 @@
+-NULL = 
+-
+-plugindir = $(PK_PLUGIN_DIR)
+-plugin_LTLIBRARIES = libpk_backend_apt2.la
+-libpk_backend_apt2_la_SOURCES = pk-backend-apt2.c
+-libpk_backend_apt2_la_LIBADD = $(PK_PLUGIN_LIBS)
+-libpk_backend_apt2_la_LDFLAGS = -module -avoid-version
+-libpk_backend_apt2_la_CFLAGS = $(PK_PLUGIN_CFLAGS)
+-
+-dbusinstancedir = $(LIBEXECDIR)
+-dbusinstance_DATA =                                     \
+-        aptDBUSBackend.py                               \
+-        $(NULL)
+-
+-EXTRA_DIST =                                            \
+-        $(dbusinstance_DATA)                            \
+-        $(NULL)
+-
+-install-data-hook:
+-      chmod a+rx $(DESTDIR)$(libexecdir)/*.py
+-
+-clean-local :
+-      rm -f *~
+-      rm -f *.pyc
+-
+diff --git a/backends/apt2/README b/backends/apt2/README
+deleted file mode 100644
+index 0a3da6e..0000000
+--- a/backends/apt2/README
++++ /dev/null
+@@ -1,23 +0,0 @@
+-The name of this backend is apt2.
+-
+-It supports apt which is mainly used by Debian and its derivates. In contrast to
+-the backend called apt this one uses DBus for the communication with the 
+-packagekit daemon. This allows to perform actions without having to reopen
+-the cache for each one.
+-
+-To provide a tremendously fast search function a Xapian database is used.
+-It is provided by Enrico Zini's apt-xapian-index. Debtags will be used to 
+-enhance the quality of the search results further.
+-
+-A list of implemented functions are listed in the PackageKit FAQ:
+-
+-http://www.packagekit.org/pk-faq.html
+-
+-You can find packages for Ubuntu here:
+-
+-https://www.launchpad.net/~packagekit/+ppa
+-
+-Packages for Debian Unstable will be provided soon.
+-
+-Feel free to send comments or bug reports to the PackageKit mailing list
+-or to the author.
+diff --git a/backends/apt2/TODO b/backends/apt2/TODO
+deleted file mode 100644
+index bee2f3d..0000000
+--- a/backends/apt2/TODO
++++ /dev/null
+@@ -1,70 +0,0 @@
+-ISSUES:
+-
+- * Support delayed or hidden debconf questions
+-
+-Unresolved issues can be discussed at the following wiki page:
+-http://wiki.debian.org/PackageKit
+-
+-
+-TODO:
+-
+- * Implement all open backend methods. A list of implemented backend methods 
+-   can be found in PackageKit FAQ or in pk-backend-apt2.c.
+-
+- * Blacklist packages requiring input on the terminal and try to change
+-   the Debian policy in the long run. Way of automation?
+- 
+- * Allow to inject alternative apt.package.Package classes into the
+-   cache to support PackageKit and distribution specific needs
+-   (e.g. when is a package called free or supported)
+-
+- * Allow to reinject debtags into the search results to get 
+-   similar software which not matches on the search terms
+-
+- * Index file list and add properties for package name and section to
+-   the xapian database to also make use of it in search group and 
+-   search name (do we want this?)
+-
+- * Map Debian/Ubuntu sections to PackageKit groups:
+-    - admin : System Administration           => admin-tools
+-    - base : Base System                      => system
+-    - comm : Communication                    => communication
+-    - devel : Development                     => programming
+-    - doc : Documentation                     => ???
+-    - editors : Editors                               => accessoires
+-    - electronics : Electronics                       => other
+-    - embedded : Embedded Devices             => system
+-    - games : Games and Amusement             => games
+-    - gnome : GNOME Desktop Environment               => desktop-gnome
+-    - graphics : Graphics                     => graphics
+-    - hamradio : Amateur Radio                        => communication
+-    - interpreters : Interpreted Computer L.  => programming
+-    - kde : KDE Desktop Environment           => desktop-kde
+-    - libdevel : Libraries - Development      => programming
+-    - libs : Libraries                                => system
+-    - mail : Email                            => internet
+-    - math : Mathematics                      => ??? science/education
+-    - misc : Miscellaneous - Text Based               => other
+-    - net : Networkinga                               => network
+-    - news : Newsgroup                                => internet
+-    - oldlibs : Libraries - Old                       => legacy
+-    - otherosfs : Cross Platform              => system
+-    - perl : Perl Programming Language                => programming
+-    - python : Python Programming Language    => programming
+-    - science : Science                               => ??? science/education
+-    - shells : Shells                         => system
+-    - sound : Multimedia                      => multimedia
+-    - tex : TeX Authoring                     => publishing
+-    - text : Word Processing                  => publishing
+-    - utils : Utilities                               => accessoires
+-    - web : World Wide Web                    => internet
+-    - x11 : Miscellaneous  - Graphical                => desktop-other
+-    - unknown : Unknown                               => unknown
+-    - alien : Converted From RPM by Alien"    => unknown
+-    - translations                            => localization
+-  The following could not be maped: science, documentation, electronics
+-  Are there any derivates with additional sections?
+-
+- * Fix the dbus policy. Should we require at_console for searching?
+- 
+-DONE:
+diff --git a/backends/apt2/aptDBUSBackend.py b/backends/apt2/aptDBUSBackend.py
+deleted file mode 100755
+index b7fc500..0000000
+--- a/backends/apt2/aptDBUSBackend.py
++++ /dev/null
+@@ -1,628 +0,0 @@
+-#!/usr/bin/env python
+-# -*- coding: utf-8 -*-
+-"""
+-Provides an apt backend to PackageKit
+-
+-Copyright (C) 2007 Ali Sabil <ali.sabil@gmail.com>
+-Copyright (C) 2007 Tom Parker <palfrey@tevp.net>
+-Copyright (C) 2008 Sebastian Heinlein <glatzor@ubuntu.com>
+-
+-Licensed under the GNU General Public License Version 2
+-
+-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 2 of the License, or
+-(at your option) any later version.
+-"""
+-
+-__author__  = "Sebastian Heinlein <devel@glatzor.de>"
+-__state__   = "experimental"
+-
+-import os
+-import pty
+-import re
+-import signal
+-import time
+-import threading
+-import warnings
+-
+-import apt
+-import apt_pkg
+-import dbus
+-import dbus.glib
+-import dbus.service
+-import dbus.mainloop.glib
+-import gobject
+-import xapian
+-
+-from packagekit.daemonBackend import PACKAGEKIT_DBUS_INTERFACE, PACKAGEKIT_DBUS_PATH, PackageKitBaseBackend, PackagekitProgress, pklog, threaded
+-from packagekit.enums import *
+-
+-warnings.filterwarnings(action='ignore', category=FutureWarning)
+-
+-PACKAGEKIT_DBUS_SERVICE = 'org.freedesktop.PackageKitAptBackend'
+-
+-XAPIANDBPATH = os.environ.get("AXI_DB_PATH", "/var/lib/apt-xapian-index")
+-XAPIANDB = XAPIANDBPATH + "/index"
+-XAPIANDBVALUES = XAPIANDBPATH + "/values"
+-DEFAULT_SEARCH_FLAGS = (xapian.QueryParser.FLAG_BOOLEAN |
+-                        xapian.QueryParser.FLAG_PHRASE |
+-                        xapian.QueryParser.FLAG_LOVEHATE |
+-                        xapian.QueryParser.FLAG_BOOLEAN_ANY_CASE)
+-
+-# Required for daemon mode
+-os.putenv("PATH",
+-          "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin")
+-# Avoid questions from the maintainer scripts as far as possible
+-os.putenv("DEBIAN_FRONTEND", "noninteractive")
+-os.putenv("APT_LISTCHANGES_FRONTEND", "none")
+-
+-# Setup threading support
+-gobject.threads_init()
+-dbus.glib.threads_init()
+-
+-class PackageKitOpProgress(apt.progress.OpProgress):
+-    '''
+-    Handle the cache opening process
+-    '''
+-    def __init__(self, backend, prange=(0,100), progress=True):
+-        self._backend = backend
+-        apt.progress.OpProgress.__init__(self)
+-        self.steps = []
+-        for v in [0.12, 0.25, 0.50, 0.75, 1.00]:
+-            s = prange[0] + (prange[1] - prange[0]) * v
+-            self.steps.append(s)
+-        self.pstart = float(prange[0])
+-        self.pend = self.steps.pop(0)
+-        self.pprev = None
+-        self.show_progress = progress
+-
+-    # OpProgress callbacks
+-    def update(self, percent):
+-        progress = int(self.pstart + percent / 100 * (self.pend - self.pstart))
+-        if self.show_progress == True and self.pprev < progress:
+-            self._backend.PercentageChanged(progress)
+-            self.pprev = progress
+-
+-    def done(self):
+-        self.pstart = self.pend
+-        try:
+-            self.pend = self.steps.pop(0)
+-        except:
+-            pklog.warning("An additional step to open the cache is required")
+-
+-class PackageKitFetchProgress(apt.progress.FetchProgress):
+-    '''
+-    Handle the package download process
+-    '''
+-    def __init__(self, backend, prange=(0,100)):
+-        self._backend = backend
+-        apt.progress.FetchProgress.__init__(self)
+-        self.pstart = prange[0]
+-        self.pend = prange[1]
+-        self.pprev = None
+-
+-    # FetchProgress callbacks
+-    def pulse(self):
+-        if self._backend._canceled.isSet():
+-            return False
+-        percent = ((self.currentBytes + self.currentItems)*100.0)/float(self.totalBytes+self.totalItems)
+-        progress = int(self.pstart + percent/100 * (self.pend - self.pstart))
+-        if self.pprev < progress:
+-            self._backend.PercentageChanged(progress)
+-            self.pprev = progress
+-        apt.progress.FetchProgress.pulse(self)
+-        return True
+-
+-    def start(self):
+-        self._backend.StatusChanged(STATUS_DOWNLOAD)
+-        self._backend.AllowCancel(True)
+-
+-    def stop(self):
+-        self._backend.PercentageChanged(self.pend)
+-        self._backend.AllowCancel(False)
+-
+-    def mediaChange(self, medium, drive):
+-        #FIXME: use the Message method to notify the user
+-        self._backend.error(ERROR_UNKNOWN,
+-                            "Medium change needed")
+-
+-class PackageKitInstallProgress(apt.progress.InstallProgress):
+-    '''
+-    Handle the installation and removal process. Bits taken from
+-    DistUpgradeViewNonInteractive.
+-    '''
+-    def __init__(self, backend, prange=(0,100)):
+-        apt.progress.InstallProgress.__init__(self)
+-        self._backend = backend
+-        self.timeout = 900
+-        self.pstart = prange[0]
+-        self.pend = prange[1]
+-        self.pprev = None
+-
+-    def statusChange(self, pkg, percent, status):
+-        progress = self.pstart + percent/100 * (self.pend - self.pstart)
+-        if self.pprev < progress:
+-            self._backend.PercentageChanged(int(progress))
+-            self.pprev = progress
+-        pklog.debug("PM status: %s" % status)
+-
+-    def startUpdate(self):
+-        self._backend.StatusChanged(STATUS_INSTALL)
+-        self.last_activity = time.time()
+-
+-    def updateInterface(self):
+-        pklog.debug("Updating interface")
+-        apt.progress.InstallProgress.updateInterface(self)
+-
+-    def conffile(self, current, new):
+-        pklog.critical("Config file prompt: '%s'" % current)
+-
+-def sigquit(signum, frame):
+-    pklog.error("Was killed")
+-    sys.exit(1)
+-
+-class PackageKitAptBackend(PackageKitBaseBackend):
+-    '''
+-    PackageKit backend for apt
+-    '''
+-
+-    def locked(func):
+-        '''
+-        Decorator to run a method with a lock
+-        '''
+-        def wrapper(*args, **kwargs):
+-            backend = args[0]
+-            backend._lock_cache()
+-            ret = func(*args, **kwargs)
+-            backend._unlock_cache()
+-            return ret
+-        wrapper.__name__ = func.__name__
+-        return wrapper
+-
+-    def __init__(self, bus_name, dbus_path):
+-        pklog.info("Initializing APT backend")
+-        signal.signal(signal.SIGQUIT, sigquit)
+-        self._cache = None
+-        self._xapian = None
+-        self._canceled = threading.Event()
+-        self._canceled.clear()
+-        self._locked = threading.Lock()
+-        PackageKitBaseBackend.__init__(self, bus_name, dbus_path)
+-
+-    # Methods ( client -> engine -> backend )
+-
+-    def doInit(self):
+-        pklog.info("Initializing cache")
+-        self.StatusChanged(STATUS_SETUP)
+-        self.AllowCancel(False)
+-        self.NoPercentageUpdates()
+-        self._open_cache(progress=False)
+-
+-    def doExit(self):
+-        pass
+-
+-    @threaded
+-    def doCancel(self):
+-        pklog.info("Canceling current action")
+-        self.StatusChanged(STATUS_CANCEL)
+-        self._canceled.set()
+-        self._canceled.wait()
+-
+-    @threaded
+-    def doSearchName(self, filters, search):
+-        '''
+-        Implement the apt2-search-name functionality
+-        '''
+-        pklog.info("Searching for package name: %s" % search)
+-        self.StatusChanged(STATUS_QUERY)
+-        self.NoPercentageUpdates()
+-        self._check_init(progress=False)
+-        self.AllowCancel(True)
+-
+-        for pkg in self._cache:
+-            if self._canceled.isSet():
+-                self.ErrorCode(ERROR_TRANSACTION_CANCELLED,
+-                               "The search was canceled")
+-                self.Finished(EXIT_KILL)
+-                self._canceled.clear()
+-                return
+-            elif search in pkg.name and self._is_package_visible(pkg, filters):
+-                self._emit_package(pkg)
+-        self.Finished(EXIT_SUCCESS)
+-
+-    @threaded
+-    def doSearchDetails(self, filters, search):
+-        '''
+-        Implement the apt2-search-details functionality
+-        '''
+-        pklog.info("Searching for package name: %s" % search)
+-        self.StatusChanged(STATUS_QUERY)
+-        self.NoPercentageUpdates()
+-        self._check_init(progress=False)
+-        self.AllowCancel(True)
+-        results = []
+-
+-        if os.access(XAPIANDB, os.R_OK):
+-            pklog.debug("Performing xapian db based search")
+-            db = xapian.Database(XAPIANDB)
+-            parser = xapian.QueryParser()
+-            query = parser.parse_query(unicode(search),
+-                                       DEFAULT_SEARCH_FLAGS)
+-            enquire = xapian.Enquire(db)
+-            enquire.set_query(query)
+-            matches = enquire.get_mset(0, 1000)
+-            for r in  map(lambda m: m[xapian.MSET_DOCUMENT].get_data(),
+-                          enquire.get_mset(0,1000)):
+-                if self._cache.has_key(r):
+-                    results.append(self._cache[r])
+-        else:
+-            pklog.debug("Performing apt cache based search")
+-            for p in self._cache._dict.values():
+-                if self._check_canceled("Search was canceled"): return
+-                needle = search.strip().lower()
+-                haystack = p.description.lower()
+-                if p.name.find(needle) >= 0 or haystack.find(needle) >= 0:
+-                    results.append(p)
+-
+-        for r in results:
+-            if self._check_canceled("Search was canceled"): return
+-            if self._is_package_visible(r, filters) == True:
+-                self._emit_package(r)
+-
+-        self.Finished(EXIT_SUCCESS)
+-
+-    @threaded
+-    @locked
+-    def doGetUpdates(self, filters):
+-        '''
+-        Implement the {backend}-get-update functionality
+-        '''
+-        #FIXME: Implment the basename filter
+-        pklog.info("Get updates")
+-        self.StatusChanged(STATUS_INFO)
+-        self.AllowCancel(True)
+-        self.NoPercentageUpdates()
+-        self._check_init(progress=False)
+-        self._cache.upgrade(False)
+-        for pkg in self._cache.getChanges():
+-            if self._canceled.isSet():
+-                self.ErrorCode(ERROR_TRANSACTION_CANCELLED,
+-                               "Calculating updates was canceled")
+-                self.Finished(EXIT_KILL)
+-                self._canceled.clear()
+-                return
+-            else:
+-                self._emit_package(pkg)
+-        self._open_cache(progress=False)
+-        self.Finished(EXIT_SUCCESS)
+-
+-    @threaded
+-    def GetDetails(self, pkg_id):
+-        '''
+-        Implement the {backend}-get-details functionality
+-        '''
+-        pklog.info("Get details of %s" % pkg_id)
+-        self.StatusChanged(STATUS_INFO)
+-        self.NoPercentageUpdates()
+-        self.AllowCancel(False)
+-        self._check_init(progress=False)
+-        name, version, arch, data = self.get_package_from_id(pkg_id)
+-        if not self._cache.has_key(name):
+-            self.ErrorCode(ERROR_PACKAGE_NOT_FOUND,
+-                           "Package %s isn't available" % name)
+-            self.Finished(EXIT_FAILED)
+-            return
+-        pkg = self._cache[name]
+-        #FIXME: should perhaps go to python-apt since we need this in
+-        #       several applications
+-        desc = pkg.description
+-        # Skip the first line - it's a duplicate of the summary
+-        i = desc.find('\n')
+-        desc = desc[i+1:]
+-        # do some regular expression magic on the description
+-        # Add a newline before each bullet
+-        p = re.compile(r'^(\s|\t)*(\*|0|-)',re.MULTILINE)
+-        desc = p.sub(ur'\n\u2022', desc)
+-        # replace all newlines by spaces
+-        p = re.compile(r'\n', re.MULTILINE)
+-        desc = p.sub(" ", desc)
+-        # replace all multiple spaces by newlines
+-        p = re.compile(r'\s\s+', re.MULTILINE)
+-        desc = p.sub('\n', desc)
+-        #FIXME: group and licence information missing
+-        self.Details(pkg_id, 'unknown', 'unknown', desc,
+-                         pkg.homepage, pkg.packageSize)
+-        self.Finished(EXIT_SUCCESS)
+-
+-    @threaded
+-    @locked
+-    def doUpdateSystem(self):
+-        '''
+-        Implement the {backend}-update-system functionality
+-        '''
+-        #FIXME: Better exception and error handling
+-        #FIXME: Distupgrade or Upgrade?
+-        #FIXME: Handle progress in a more sane way
+-        pklog.info("Upgrading system")
+-        self.StatusChanged(STATUS_UPDATE)
+-        self.AllowCancel(False)
+-        self.PercentageChanged(0)
+-        self._check_init(prange=(0,5))
+-        try:
+-            self._cache.upgrade(distUpgrade=True)
+-            self._cache.commit(PackageKitFetchProgress(self, prange=(5,50)),
+-                               PackageKitInstallProgress(self, prange=(50,95)))
+-        except apt.cache.FetchFailedException:
+-            self._open_cache()
+-            self.ErrorCode(ERROR_PACKAGE_DOWNLOAD_FAILED, "Download failed")
+-            self.Finished(EXIT_FAILED)
+-            return
+-        except apt.cache.FetchCancelledException:
+-            self._open_cache(prange=(95,100))
+-            self.ErrorCode(ERROR_TRANSACTION_CANCELLED, "Download was canceled")
+-            self.Finished(EXIT_KILL)
+-            self._canceled.clear()
+-            return
+-        except:
+-            self._open_cache(prange=(95,100))
+-            self.ErrorCode(ERROR_UNKNOWN, "System update failed")
+-            self.Finished(EXIT_FAILED)
+-            return
+-        self.PercentageChanged(100)
+-        self.Finished(EXIT_SUCCESS)
+-
+-    @threaded
+-    @locked
+-    def doRemovePackages(self, ids, deps=True, auto=False):
+-        '''
+-        Implement the {backend}-remove functionality
+-        '''
+-        #FIXME: Handle progress in a more sane way
+-        pklog.info("Removing package with id %s" % id)
+-        self.StatusChanged(STATUS_REMOVE)
+-        self.AllowCancel(False)
+-        self.PercentageChanged(0)
+-        self._check_init(prange=(0,10))
+-        pkg = self._find_package_by_id(id)
+-        if pkg == None:
+-            self.ErrorCode(ERROR_PACKAGE_NOT_FOUND,
+-                           "Package %s isn't available" % pkg.name)
+-            self.Finished(EXIT_FAILED)
+-            return
+-        if not pkg.isInstalled:
+-            self.ErrorCode(ERROR_PACKAGE_NOT_INSTALLED,
+-                           "Package %s isn't installed" % pkg.name)
+-            self.Finished(EXIT_FAILED)
+-            return
+-        name = pkg.name[:]
+-        try:
+-            pkg.markDelete()
+-            self._cache.commit(PackageKitFetchProgress(self, prange=(10,10)),
+-                               PackageKitInstallProgress(self, prange=(10,90)))
+-        except:
+-            self._open_cache(prange=(90,100))
+-            self.ErrorCode(ERROR_UNKNOWN, "Removal failed")
+-            self.Finished(EXIT_FAILED)
+-            return
+-        self._open_cache(prange=(90,100))
+-        self.PercentageChanged(100)
+-        if not self._cache.has_key(name) or not self._cache[name].isInstalled:
+-            self.Finished(EXIT_SUCCESS)
+-        else:
+-            self.ErrorCode(ERROR_UNKNOWN, "Package is still installed")
+-            self.Finished(EXIT_FAILED)
+-
+-    @threaded
+-    @locked
+-    def doInstallPackages(self, ids):
+-        '''
+-        Implement the {backend}-install functionality
+-        '''
+-        #FIXME: Handle progress in a more sane way
+-        pklog.info("Installing package with id %s" % id)
+-        self.StatusChanged(STATUS_INSTALL)
+-        self.AllowCancel(False)
+-        self.PercentageChanged(0)
+-        self._check_init(prange=(0,10))
+-        pkg = self._find_package_by_id(id)
+-        if pkg == None:
+-            self.ErrorCode(ERROR_PACKAGE_NOT_FOUND,
+-                           "Package %s isn't available" % pkg.name)
+-            self.Finished(EXIT_FAILED)
+-            return
+-        if pkg.isInstalled:
+-            self.ErrorCode(ERROR_PACKAGE_ALREADY_INSTALLED,
+-                           "Package %s is already installed" % pkg.name)
+-            self.Finished(EXIT_FAILED)
+-            return
+-        name = pkg.name[:]
+-        try:
+-            pkg.markInstall()
+-            self._cache.commit(PackageKitFetchProgress(self, prange=(10,50)),
+-                               PackageKitInstallProgress(self, prange=(50,90)))
+-        except:
+-            self._open_cache(prange=(90,100))
+-            self.ErrorCode(ERROR_UNKNOWN, "Installation failed")
+-            self.Finished(EXIT_FAILED)
+-            return
+-        self._open_cache(prange=(90,100))
+-        self.PercentageChanged(100)
+-        if self._cache.has_key(name) and self._cache[name].isInstalled:
+-            self.Finished(EXIT_SUCCESS)
+-        else:
+-            self.ErrorCode(ERROR_UNKNOWN, "Installation failed")
+-            self.Finished(EXIT_FAILED)
+-
+-    @threaded
+-    @locked
+-    def doRefreshCache(self, force):
+-        '''
+-        Implement the {backend}-refresh_cache functionality
+-        '''
+-        pklog.info("Refresh cache")
+-        self.StatusChanged(STATUS_REFRESH_CACHE)
+-        self.last_action_time = time.time()
+-        self.AllowCancel(False);
+-        self.PercentageChanged(0)
+-        self._check_init((0,10))
+-        try:
+-            self._cache.update(PackageKitFetchProgress(self, prange=(10,95)))
+-        except apt.cache.FetchFailedException:
+-            self.ErrorCode(ERROR_NO_NETWORK, "Download failed")
+-            self.Finished(EXIT_FAILED)
+-            return
+-        except apt.cache.FetchCancelledException:
+-            self._canceled.clear()
+-            self.ErrorCode(ERROR_TRANSACTION_CANCELLED, "Download was canceled")
+-            self.Finished(EXIT_KILL)
+-            return
+-        except:
+-            self._open_cache(prange=(95,100))
+-            self.ErrorCode(ERROR_UNKNOWN, "Refreshing cache failed")
+-            self.Finished(EXIT_FAILED)
+-            return
+-        self.PercentageChanged(100)
+-        self.Finished(EXIT_SUCCESS)
+-
+-    # Helpers
+-
+-    def _open_cache(self, prange=(0,100), progress=True):
+-        '''
+-        (Re)Open the APT cache
+-        '''
+-        pklog.debug("Open APT cache")
+-        self.StatusChanged(STATUS_REFRESH_CACHE)
+-        try:
+-            self._cache = apt.Cache(PackageKitOpProgress(self, prange,
+-                                                         progress))
+-        except:
+-            self.ErrorCode(ERROR_NO_CACHE, "Package cache could not be opened")
+-            self.Finished(EXIT_FAILED)
+-            self.Exit()
+-            return
+-        if self._cache._depcache.BrokenCount > 0:
+-            self.ErrorCode(ERROR_DEP_RESOLUTION_FAILED,
+-                           "Not all dependecies can be satisfied")
+-            self.Finished(EXIT_FAILED)
+-            self.Exit()
+-            return
+-
+-    def _lock_cache(self):
+-        '''
+-        Lock the cache
+-        '''
+-        pklog.debug("Locking cache")
+-        self._locked.acquire()
+-
+-    def _unlock_cache(self):
+-        '''
+-        Unlock the cache
+-        '''
+-        pklog.debug("Releasing cache")
+-        self._locked.release()
+-
+-    def _check_init(self, prange=(0,10), progress=True):
+-        '''
+-        Check if the backend was initialized well and try to recover from
+-        a broken setup
+-        '''
+-        pklog.debug("Check apt cache and xapian database")
+-        if not isinstance(self._cache, apt.cache.Cache) or \
+-           self._cache._depcache.BrokenCount > 0:
+-            self._open_cache(prange, progress)
+-
+-    def _check_canceled(self, msg):
+-        '''
+-        Check if the current transaction was canceled. If so send the
+-        corresponding error message and return True
+-        '''
+-        if self._canceled.isSet():
+-             self.ErrorCode(ERROR_TRANSACTION_CANCELLED, msg)
+-             self.Finished(EXIT_KILL)
+-             self._canceled.clear()
+-             return True
+-        return False
+- 
+-    def get_id_from_package(self, pkg, installed=False):
+-        '''
+-        Return the id of the installation candidate of a core
+-        apt package. If installed is set to True the id of the currently
+-        installed package will be returned.
+-        '''
+-        origin = ''
+-        if installed == False and pkg.isInstalled:
+-            pkgver = pkg.installedVersion
+-        else:
+-            pkgver = pkg.candidateVersion
+-            if pkg.candidateOrigin:
+-                origin = pkg.candidateOrigin[0].label
+-        id = self._get_package_id(pkg.name, pkgver, pkg.architecture, origin)
+-        return id
+-
+-    def _emit_package(self, pkg):
+-        '''
+-        Send the Package signal for a given apt package
+-        '''
+-        id = self.get_id_from_package(pkg)
+-        if pkg.isInstalled:
+-            status = INFO_INSTALLED
+-        else:
+-            status = INFO_AVAILABLE
+-        summary = pkg.summary
+-        self.Package(status, id, summary)
+-
+-    def _is_package_visible(self, pkg, filters):
+-        '''
+-        Return True if the package should be shown in the user interface
+-        '''
+-        #FIXME: Needs to be optmized
+-        if filters == 'none':
+-            return True
+-        if FILTER_INSTALLED in filters and not pkg.isInstalled:
+-            return False
+-        if FILTER_NOT_INSTALLED in filters and pkg.isInstalled:
+-            return False
+-        if FILTER_GUI in filters and not self._package_has_gui(pkg):
+-            return False
+-        if FILTER_NOT_GUI in filters and self._package_has_gui(pkg):
+-            return False
+-        if FILTER_DEVELOPMENT in filters and not self._package_is_devel(pkg):
+-            return False
+-        if FILTER_NOT_DEVELOPMENT in filters and self._package_is_devel(pkg):
+-            return False
+-        return True
+-
+-    def _package_has_gui(self, pkg):
+-        #FIXME: should go to a modified Package class
+-        #FIXME: take application data into account. perhaps checking for
+-        #       property in the xapian database
+-        return pkg.section.split('/')[-1].lower() in ['x11', 'gnome', 'kde']
+-
+-    def _package_is_devel(self, pkg):
+-        #FIXME: should go to a modified Package class
+-        return pkg.name.endswith("-dev") or pkg.name.endswith("-dbg") or \
+-               pkg.section.split('/')[-1].lower() in ['devel', 'libdevel']
+-
+-    def _find_package_by_id(self, id):
+-        '''
+-        Return a package matching to the given package id
+-        '''
+-        # FIXME: Perform more checks
+-        name, version, arch, data = self.get_package_from_id(id)
+-        if self._cache.has_key(name):
+-            return self._cache[name]
+-        else:
+-            return None
+-
+-
+-def main():
+-    loop = dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+-    bus = dbus.SystemBus(mainloop=loop)
+-    bus_name = dbus.service.BusName(PACKAGEKIT_DBUS_SERVICE, bus=bus)
+-    manager = PackageKitAptBackend(bus_name, PACKAGEKIT_DBUS_PATH)
+-
+-if __name__ == '__main__':
+-    main()
+-
+-# vim: ts=4 et sts=4
+diff --git a/backends/apt2/pk-backend-apt2.c b/backends/apt2/pk-backend-apt2.c
+deleted file mode 100644
+index 4f78ec4..0000000
+--- a/backends/apt2/pk-backend-apt2.c
++++ /dev/null
+@@ -1,204 +0,0 @@
+-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+- *
+- * Copyright (C) 2007 Ali Sabil <ali.sabil@gmail.com>
+- * Copyright (C) 2007 Tom Parker <palfrey@tevp.net>
+- *
+- * Licensed under the GNU General Public License Version 2
+- *
+- * 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 2 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, write to the Free Software
+- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+- */
+-
+-#include <pk-backend.h>
+-#include <pk-backend-dbus.h>
+-
+-static PkBackendDbus *dbus;
+-
+-#define PK_DBUS_BACKEND_SERVICE_APT   "org.freedesktop.PackageKitAptBackend"
+-
+-/**
+- * backend_initialize:
+- * This should only be run once per backend load, i.e. not every transaction
+- */
+-static void
+-backend_initialize (PkBackend *backend)
+-{
+-      pk_debug ("FILTER: initialize");
+-      dbus = pk_backend_dbus_new ();
+-      pk_backend_dbus_set_name (dbus, PK_DBUS_BACKEND_SERVICE_APT);
+-}
+-
+-/**
+- * backend_destroy:
+- * This should only be run once per backend load, i.e. not every transaction
+- */
+-static void
+-backend_destroy (PkBackend *backend)
+-{
+-      pk_debug ("FILTER: destroy");
+-      pk_backend_dbus_kill (dbus);
+-      g_object_unref (dbus);
+-}
+-
+-/**
+- * backend_get_groups:
+- */
+-static PkGroupEnum
+-backend_get_groups (PkBackend *backend)
+-{
+-      return (PK_GROUP_ENUM_ACCESSORIES |
+-              PK_GROUP_ENUM_GAMES |
+-              PK_GROUP_ENUM_GRAPHICS |
+-              PK_GROUP_ENUM_INTERNET |
+-              PK_GROUP_ENUM_OFFICE |
+-              PK_GROUP_ENUM_OTHER |
+-              PK_GROUP_ENUM_PROGRAMMING |
+-              PK_GROUP_ENUM_MULTIMEDIA |
+-              PK_GROUP_ENUM_SYSTEM);
+-}
+-
+-/**
+- * backend_get_filters:
+- */
+-static PkFilterEnum
+-backend_get_filters (PkBackend *backend)
+-{
+-      return (PK_FILTER_ENUM_GUI |
+-              PK_FILTER_ENUM_INSTALLED |
+-              PK_FILTER_ENUM_DEVELOPMENT);
+-}
+-
+-/**
+- * backend_get_updates:
+- */
+-static void
+-backend_get_updates (PkBackend *backend, PkFilterEnum filters)
+-{
+-      pk_backend_dbus_get_updates (dbus, filters);
+-}
+-
+-/**
+- * backend_refresh_cache:
+- * */
+-static void
+-backend_refresh_cache (PkBackend *backend, gboolean force)
+-{
+-      // check network state
+-      if (!pk_backend_is_online (backend)) {
+-              pk_backend_error_code (backend, PK_ERROR_ENUM_NO_NETWORK, "Cannot refresh cache whilst offline");
+-              pk_backend_finished (backend);
+-              return;
+-      }
+-
+-      pk_backend_dbus_refresh_cache(dbus, force);
+-}
+-
+-/**
+- * pk_backend_update_system:
+- * */
+-static void
+-backend_update_system (PkBackend *backend)
+-{
+-      pk_backend_dbus_update_system (dbus);
+-}
+-
+-/**
+- * backend_install_packages
+- *  */
+-static void
+-backend_install_packages (PkBackend *backend, gchar **package_ids)
+-{
+-      pk_backend_dbus_install_packages (dbus, package_ids);
+-}
+-
+-/**
+- * backend_remove_packages
+- *  */
+-static void
+-backend_remove_packages (PkBackend *backend, gchar **package_ids, gboolean allow_deps, gboolean autoremove)
+-{
+-      pk_backend_dbus_remove_packages (dbus, package_ids, allow_deps, autoremove);
+-}
+-
+-/**
+- * backend_get_details:
+- *  */
+-static void
+-backend_get_details (PkBackend *backend, const gchar *package_id)
+-{
+-      pk_backend_dbus_get_details (dbus, package_id);
+-}
+-
+-/**
+- *  * pk_backend_search_details:
+- *   */
+-static void
+-backend_search_details (PkBackend *backend, PkFilterEnum filters, const gchar *search)
+-{
+-      pk_backend_dbus_search_details (dbus, filters, search);
+-}
+-
+-/**
+- *  * pk_backend_search_name:
+- *   */
+-static void
+-backend_search_name (PkBackend *backend, PkFilterEnum filters, const gchar *search)
+-{
+-      pk_backend_dbus_search_name (dbus, filters, search);
+-}
+-
+-/**
+- *  * pk_backend_cancel:
+- *   */
+-static void
+-backend_cancel (PkBackend *backend)
+-{
+-      pk_backend_dbus_cancel (dbus);
+-}
+-
+-
+-PK_BACKEND_OPTIONS (
+-      "Apt",                                  /* description */
+-      "Ali Sabil <ali.sabil@gmail.com>; Tom Parker <palfrey@tevp.net>; Sebastian Heinlein <glatzor@ubuntu.com>",      /* author */
+-      backend_initialize,                     /* initalize */
+-      backend_destroy,                        /* destroy */
+-      backend_get_groups,                     /* get_groups */
+-      backend_get_filters,                    /* get_filters */
+-      backend_cancel,                         /* cancel */
+-      NULL,                                   /* get_depends */
+-      backend_get_details,                    /* get_details */
+-      NULL,                                   /* get_files */
+-      NULL,                                   /* get_packages */
+-      NULL,                                   /* get_repo_list */
+-      NULL,                                   /* get_requires */
+-      NULL,                                   /* get_update_detail */
+-      backend_get_updates,                    /* get_updates */
+-      NULL,                                   /* install_files */
+-      backend_install_packages,               /* install_packages */
+-      NULL,                                   /* install_signature */
+-      backend_refresh_cache,                  /* refresh_cache */
+-      backend_remove_packages,                /* remove_packages */
+-      NULL,                                   /* repo_enable */
+-      NULL,                                   /* repo_set_data */
+-      NULL,                                   /* resolve */
+-      NULL,                                   /* rollback */
+-      backend_search_details,                 /* search_details */
+-      NULL,                                   /* search_file */
+-      NULL,                                   /* search_group */
+-      backend_search_name,                    /* search_name */
+-      NULL,                                   /* service_pack */
+-      NULL,                                   /* update_packages */
+-      backend_update_system,                  /* update_system */
+-      NULL                                    /* what_provides */
+-);
+diff --git a/backends/apt2/profiler.py b/backends/apt2/profiler.py
+deleted file mode 100644
+index 1b5d30f..0000000
+--- a/backends/apt2/profiler.py
++++ /dev/null
+@@ -1,40 +0,0 @@
+-#!/usr/bin/env python
+-# Licensed under the GNU General Public License Version 2
+-#
+-# 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 2 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, write to the Free Software
+-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-
+-# Copyright (C) 2008
+-#    Sebastian Heinlein <sebi@glatzor.de>
+-
+-"""
+-Allows to start the apt2 backend in a profling mode
+-"""
+-
+-__author__ = "Sebastian Heinlein <devel@glatzor.de>"
+-
+-
+-import hotshot
+-import sys
+-
+-from aptDBUSBackend import main
+-
+-if len(sys.argv) == 2:
+-    profile = sys.argv[1]
+-else:
+-    profile = "profile"
+-
+-prof = hotshot.Profile(profile)
+-print prof.runcall(main)
+-prof.close()
+diff --git a/backends/apt2/test.py b/backends/apt2/test.py
+deleted file mode 100755
+index a1d5ffb..0000000
+--- a/backends/apt2/test.py
++++ /dev/null
+@@ -1,98 +0,0 @@
+-#!/usr/bin/python
+-# Licensed under the GNU General Public License Version 2
+-#
+-# 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 2 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, write to the Free Software
+-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-
+-# Copyright (C) 2007
+-#    Tim Lauridsen <timlau@fedoraproject.org>
+-
+-import sys
+-import dbus
+-from packagekit.enums import *
+-
+-PACKAGEKIT_DBUS_SERVICE = 'org.freedesktop.PackageKitAptBackend'
+-PACKAGEKIT_DBUS_INTERFACE = 'org.freedesktop.PackageKitBackend'
+-PACKAGEKIT_DBUS_PATH = '/org/freedesktop/PackageKitBackend'
+-PKG_ID = 'xterm;232-1;i386;Debian'
+-
+-try:
+-    bus = dbus.SystemBus()
+-except dbus.DBusException, e:
+-    print  "Unable to connect to dbus"
+-    print "%s" %(e,)
+-    sys.exit(1)
+-
+-try:
+-    proxy = bus.get_object(PACKAGEKIT_DBUS_SERVICE, PACKAGEKIT_DBUS_PATH)
+-    iface = dbus.Interface(proxy, PACKAGEKIT_DBUS_INTERFACE)
+-    cmd = sys.argv[1]
+-    if cmd == 'init' or cmd == 'all':
+-        print "Testing Init()"
+-        iface.Init()
+-    if cmd == 'cancel':
+-        print "Canceling"
+-        iface.Cancel()
+-    if cmd == 'get-updates' or cmd == 'all':
+-        print "Testing GetUpdate()"
+-        iface.GetUpdates()
+-    if cmd == 'search-name' or cmd == 'all':
+-        print "Testing SearchName(FILTER_NONE,'apt')"
+-        iface.SearchName(FILTER_NONE,'apt')
+-    if cmd == 'search-details' or cmd == 'all':
+-        print "SearchDetails(FILTER_NONE,'dbus')"
+-        iface.SearchDetails(FILTER_NONE,'dbus')
+-    if cmd == 'search-group' or cmd == 'all':
+-        print "Testing SearchGroup(FILTER_NONE,GROUP_GAMES)"
+-        iface.SearchGroup(FILTER_NONE,GROUP_GAMES)
+-    if cmd == 'search-file' or cmd == 'all':
+-        print "Testing SearchFile(FILTER_NONE,'/usr/bin/yum')"
+-        iface.SearchFile(FILTER_NONE,'/usr/bin/yum')
+-    if cmd == 'get-requires' or cmd == 'all':
+-        print "Testing GetRequires(PKG_ID,False)"
+-        iface.GetRequires(PKG_ID,False)
+-    if cmd == 'get-depends' or cmd == 'all':
+-        print "Testing GetDepends(PKG_ID,False)"
+-        iface.GetDepends(PKG_ID,False)
+-    if cmd == 'refresh-cache' or cmd == 'all':
+-        print "Testing RefreshCache()"
+-        iface.RefreshCache()
+-    if cmd == 'resolve' or cmd == 'all':
+-        print "Testing Resolve(FILTER_NONE,'yum')"
+-        iface.Resolve(FILTER_NONE,'yum')
+-    if cmd == 'get-details' or cmd == 'all':
+-        print "Testing GetDetails(PKG_ID)"
+-        iface.GetDetails(PKG_ID)
+-    if cmd == 'get-files' or cmd == 'all':
+-        print "Testing GetFiles(PKG_ID)"
+-        iface.GetFiles(PKG_ID)
+-    if cmd == 'get-packages' or cmd == 'all':
+-        print "Testing GetPackages(FILTER_INSTALLED,'no')"
+-        iface.GetPackages(FILTER_INSTALLED,'no')
+-    if cmd == 'get-repolist' or cmd == 'all':
+-        print "Testing GetRepoList()"
+-        iface.GetRepoList()
+-    if cmd == 'get-updatedetail' or cmd == 'all':
+-        print "Testing GetUpdateDetail(PKG_ID)"
+-        iface.GetUpdateDetail(PKG_ID)
+-    #print "Testing "
+-    #iface.
+-    if cmd == 'exit' or cmd == 'all':
+-        print "Testing Exit()"
+-        iface.Exit()
+-    
+-except dbus.DBusException, e:
+-    print "Unable to send message on dbus"
+-    print "%s" %(e,)
+-    sys.exit(1)
+diff --git a/backends/dummy/pk-backend-dummy.c b/backends/dummy/pk-backend-dummy.c
+index 2df445e..5714e9f 100644
+--- a/backends/dummy/pk-backend-dummy.c
++++ b/backends/dummy/pk-backend-dummy.c
+@@ -187,6 +187,7 @@ backend_get_update_detail_timeout (gpointer data)
+                                         "", PK_RESTART_ENUM_NONE, "Update to newest upstream source");
+       } else if (pk_strequal (_package_id, "kernel;2.6.23-0.115.rc3.git1.fc8;i386;installed")) {
+               pk_backend_update_detail (backend, "kernel;2.6.23-0.115.rc3.git1.fc8;i386;available",
++                                        "kernel;2.6.22-0.104.rc3.git6.fc8;i386;installed^"
+                                         "kernel;2.6.22-0.105.rc3.git7.fc8;i386;installed", "",
+                                         "http://www.distro-update.org/page?moo;Bugfix release for kernel",
+                                         "http://bgzilla.fd.org/result.php?#12344;Freedesktop Bugzilla #12344;"
+@@ -199,7 +200,11 @@ backend_get_update_detail_timeout (gpointer data)
+                                         "http://www.distro-update.org/page?moo;Bugfix release for gtkhtml",
+                                         "http://bgzilla.gnome.org/result.php?#9876;GNOME Bugzilla #9876",
+                                         NULL,
+-                                        PK_RESTART_ENUM_SESSION, "Update to latest whizz bang version");
++                                        PK_RESTART_ENUM_SESSION,
++                                        "Update to latest whizz bang version\n"
++                                        "* support this new thing\n"
++                                        "* something else\n"
++                                        "- and that new thing");
+       } else {
+               pk_backend_message (backend, PK_MESSAGE_ENUM_DAEMON, "Got unexpected package_id '%s'", _package_id);
+       }
+diff --git a/backends/opkg/pk-backend-opkg.c b/backends/opkg/pk-backend-opkg.c
+index 7649bab..2d70108 100644
+--- a/backends/opkg/pk-backend-opkg.c
++++ b/backends/opkg/pk-backend-opkg.c
+@@ -115,6 +115,39 @@ opkg_check_tag (opkg_package_t *pkg, gchar *tag)
+               return FALSE;
+ }
++static void
++handle_install_error (PkBackend *backend, int err)
++{
++      switch (err)
++      {
++      case OPKG_NO_ERROR:
++              break;
++      case OPKG_PACKAGE_NOT_INSTALLED:
++              pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_NOT_INSTALLED, NULL);
++              break;
++      case OPKG_PACKAGE_ALREADY_INSTALLED:
++              pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_ALREADY_INSTALLED, NULL);
++              break;
++      case OPKG_GPG_ERROR:
++              pk_backend_error_code (backend, PK_ERROR_ENUM_GPG_FAILURE, NULL);
++              break;
++      case OPKG_DOWNLOAD_FAILED:
++              pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_DOWNLOAD_FAILED, NULL);
++              break;
++      case OPKG_DEPENDENCIES_FAILED:
++              pk_backend_error_code (backend, PK_ERROR_ENUM_DEP_RESOLUTION_FAILED, NULL);
++              break;
++      case OPKG_MD5_ERROR:
++              pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_CORRUPT, NULL);
++              break;
++      case OPKG_PACKAGE_NOT_AVAILABLE:
++              pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_NOT_FOUND, NULL);
++              break;
++      default:
++              opkg_unknown_error (backend, err, "Update package");
++      }
++}
++
+ /**
+  * backend_initialize:
+  */
+@@ -387,22 +420,9 @@ backend_install_packages_thread (PkBackend *backend)
+               pi = pk_package_id_new_from_string (package_ids[0]);
+               err = opkg_install_package (opkg, pi->name, pk_opkg_progress_cb, backend);
+-              switch (err)
+-              {
+-              case OPKG_NO_ERROR:
+-                      break;
+-              case OPKG_DEPENDANCIES_FAILED:
+-                      pk_backend_error_code (backend, PK_ERROR_ENUM_DEP_RESOLUTION_FAILED, NULL);
+-                      break;
+-              case OPKG_PACKAGE_ALREADY_INSTALLED:
+-                      pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_ALREADY_INSTALLED, NULL);
+-                      break;
+-              case OPKG_PACKAGE_NOT_AVAILABLE:
+-                      pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_NOT_FOUND, NULL);
+-                      break;
+-              default:
+-                      opkg_unknown_error (backend, err, "Install");
+-              }
++              if (err)
++                      handle_install_error (backend, err);
++
+               pk_package_id_free (pi);
+               if (err != 0)
+                       break;
+@@ -551,16 +571,9 @@ backend_update_package_thread (PkBackend *backend)
+       }
+       err = opkg_upgrade_package (opkg, pi->name, pk_opkg_progress_cb, backend);
+-      switch (err)
+-      {
+-      case OPKG_NO_ERROR:
+-              break;
+-      case OPKG_PACKAGE_NOT_INSTALLED:
+-              pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_NOT_INSTALLED, NULL);
+-              break;
+-      default:
+-              opkg_unknown_error (backend, err, "Update package");
+-      }
++      if (err)
++              handle_install_error (backend, err);
++
+       pk_package_id_free (pi);
+       pk_backend_finished (backend);
+diff --git a/backends/poldek/pk-backend-poldek.c b/backends/poldek/pk-backend-poldek.c
+index fdc99d3..2691414 100644
+--- a/backends/poldek/pk-backend-poldek.c
++++ b/backends/poldek/pk-backend-poldek.c
+@@ -53,7 +53,33 @@ enum {
+       SEARCH_ENUM_NAME,
+       SEARCH_ENUM_GROUP,
+       SEARCH_ENUM_DETAILS,
+-      SEARCH_ENUM_FILE
++      SEARCH_ENUM_FILE,
++      SEARCH_ENUM_PROVIDES
++};
++
++typedef struct {
++      PkGroupEnum     group;
++      const gchar     *regex;
++} PLDGroupRegex;
++
++static PLDGroupRegex group_perlre[] = {
++      {PK_GROUP_ENUM_ACCESSORIES, "/.*Archiving\\|.*Dictionaries/"},
++      {PK_GROUP_ENUM_ADMIN_TOOLS, "/.*Databases.*\\|.*Admin/"},
++      {PK_GROUP_ENUM_COMMUNICATION, "/.*Communications/"},
++      {PK_GROUP_ENUM_EDUCATION, "/.*Engineering\\|.*Math\\|.*Science/"},
++      {PK_GROUP_ENUM_FONTS, "/Fonts/"},
++      {PK_GROUP_ENUM_GAMES, "/.*Games.*/"},
++      {PK_GROUP_ENUM_GRAPHICS, "/.*Graphics/"},
++      {PK_GROUP_ENUM_LOCALIZATION, "/I18n/"},
++      {PK_GROUP_ENUM_MULTIMEDIA, "/.*Multimedia\\|.*Sound/"},
++      {PK_GROUP_ENUM_NETWORK, "/.*Networking.*\\|/.*Mail\\|.*News\\|.*WWW/"},
++      {PK_GROUP_ENUM_OFFICE, "/.*Editors.*\\|.*Spreadsheets/"},
++      {PK_GROUP_ENUM_OTHER, "/^Applications$\\|.*Console\\|.*Emulators\\|.*File\\|.*Printing\\|.*Terminal\\|.*Text\\|Documentation\\|^Libraries.*\\|^Themes.*\\|^X11$\\|.*Amusements\\|^X11\\/Applications$\\|^X11\\/Libraries$\\|.*Window\\ Managers.*/"},
++      {PK_GROUP_ENUM_PROGRAMMING, "/.*Development.*/"},
++      {PK_GROUP_ENUM_PUBLISHING, "/.*Publishing.*/"},
++      {PK_GROUP_ENUM_SERVERS, "/Daemons\\|.*Servers/"},
++      {PK_GROUP_ENUM_SYSTEM, "/.*Shells\\|.*System\\|Base.*/"},
++      {0, NULL}
+ };
+ typedef struct {
+@@ -501,6 +527,79 @@ poldek_pkg_set_installed (struct pkg *pkg, gboolean installed) {
+ }
+ /**
++ * pld_group_to_enum:
++ *
++ * Converts PLD RPM group to PkGroupEnum.
++ **/
++static PkGroupEnum
++pld_group_to_enum (const gchar *group)
++{
++      g_return_val_if_fail (group != NULL, PK_GROUP_ENUM_OTHER);
++
++      if (strstr (group, "Archiving") != NULL ||
++          strstr (group, "Dictionaries") != NULL)
++              return PK_GROUP_ENUM_ACCESSORIES;
++      else if (strstr (group, "Databases") != NULL ||
++               strstr (group, "Admin") != NULL)
++              return PK_GROUP_ENUM_ADMIN_TOOLS;
++      else if (strstr (group, "Communications") != NULL)
++              return PK_GROUP_ENUM_COMMUNICATION;
++      else if (strstr (group, "Engineering") != NULL ||
++               strstr (group, "Math") != NULL ||
++               strstr (group, "Science") != NULL)
++              return PK_GROUP_ENUM_EDUCATION;
++      else if (strcmp (group, "Fonts") == 0)
++              return PK_GROUP_ENUM_FONTS;
++      else if (strstr (group, "Games") != NULL)
++              return PK_GROUP_ENUM_GAMES;
++      else if (strstr (group, "Graphics") != NULL)
++              return PK_GROUP_ENUM_GRAPHICS;
++      else if (strcmp (group, "I18n") == 0)
++              return PK_GROUP_ENUM_LOCALIZATION;
++      else if (strstr (group, "Multimedia") != NULL ||
++               strstr (group, "Sound") != NULL)
++              return PK_GROUP_ENUM_MULTIMEDIA;
++      else if (strstr (group, "Networking") != NULL ||
++               strstr (group, "Mail") != NULL ||
++               strstr (group, "News") != NULL ||
++               strstr (group, "WWW") != NULL)
++              return PK_GROUP_ENUM_NETWORK;
++      else if (strstr (group, "Editors") != NULL ||
++               strstr (group, "Spreadsheets") != NULL)
++              return PK_GROUP_ENUM_OFFICE;
++      else if (strstr (group, "Development") != NULL)
++              return PK_GROUP_ENUM_PROGRAMMING;
++      else if (strstr (group, "Publishing") != NULL)
++              return PK_GROUP_ENUM_PUBLISHING;
++      else if (strstr (group, "Daemons") != NULL ||
++               strstr (group, "Servers") != NULL)
++              return PK_GROUP_ENUM_SERVERS;
++      else if (strstr (group, "Shells") != NULL ||
++               strstr (group, "System") != NULL ||
++               strstr (group, "Base") != NULL)
++              return PK_GROUP_ENUM_SYSTEM;
++      else
++              return PK_GROUP_ENUM_OTHER;
++}
++
++/**
++ * pld_group_get_regex_from_enum:
++ **/
++static const gchar*
++pld_group_get_regex_from_enum (PkGroupEnum value)
++{
++      gint i;
++
++      for (i = 0;; i++) {
++              if (group_perlre[i].regex == NULL)
++                      return NULL;
++
++              if (group_perlre[i].group == value)
++                      return group_perlre[i].regex;
++      }
++}
++
++/**
+  * poldek_pkg_evr:
+  */
+ static gchar*
+@@ -916,7 +1015,8 @@ poldek_pkg_is_gui (struct pkg *pkg)
+ static gboolean
+ search_package_thread (PkBackend *backend)
+ {
+-      PkFilterEnum filters;
++      PkFilterEnum            filters;
++      PkProvidesEnum          provides;
+       gchar                   *search_cmd = NULL;
+       struct poclidek_rcmd    *cmd = NULL;
+       const gchar *search;
+@@ -930,30 +1030,38 @@ search_package_thread (PkBackend *backend)
+       search = pk_backend_get_string (backend, "search");
+       filters = pk_backend_get_uint (backend, "filters");
+-      switch (mode) {
+-              /* GetPackages */
+-              case SEARCH_ENUM_NONE:
+-                      search_cmd = g_strdup ("ls -q");
+-                      break;
+-              /* SearchName */
+-              case SEARCH_ENUM_NAME:
+-                      search_cmd = g_strdup_printf ("ls -q *%s*", search);
+-                      break;
+-              /* SearchGroup */
+-              case SEARCH_ENUM_GROUP:
+-                      search_cmd = g_strdup_printf ("search -qg *%s*", search);
+-                      break;
+-              /* SearchDetails */
+-              case SEARCH_ENUM_DETAILS:
+-                      search_cmd = g_strdup_printf ("search -dsq *%s*", search);
+-                      break;
+-              /* SearchFile */
+-              case SEARCH_ENUM_FILE:
+-                      search_cmd = g_strdup_printf ("search -qlf *%s*", search);
+-                      break;
+-              default:
+-                      /* Error */
+-                      break;
++      /* GetPackages*/
++      if (mode == SEARCH_ENUM_NONE) {
++              search_cmd = g_strdup ("ls -q");
++      /* SearchName */
++      } else if (mode == SEARCH_ENUM_NAME) {
++              search_cmd = g_strdup_printf ("ls -q *%s*", search);
++      /* SearchGroup */
++      } else if (mode == SEARCH_ENUM_GROUP) {
++              PkGroupEnum     group;
++              const gchar     *regex;
++
++              group = pk_group_enum_from_text (search);
++              regex = pld_group_get_regex_from_enum (group);
++
++              search_cmd = g_strdup_printf ("search -qg --perlre %s", regex);
++      /* SearchDetails */
++      } else if (mode == SEARCH_ENUM_DETAILS) {
++              search_cmd = g_strdup_printf ("search -dsq *%s*", search);
++      /* SearchFile */
++      } else if (mode == SEARCH_ENUM_FILE) {
++              search_cmd = g_strdup_printf ("search -qlf *%s*", search);
++      /* WhatProvides */
++      } else if (mode == SEARCH_ENUM_PROVIDES) {
++              provides = pk_backend_get_uint (backend, "provides");
++
++              if (provides == PK_PROVIDES_ENUM_ANY) {
++                      search_cmd = g_strdup_printf ("search -qp %s", search);
++              } else if (provides == PK_PROVIDES_ENUM_MODALIAS) {
++              } else if (provides == PK_PROVIDES_ENUM_CODEC) {
++              } else if (provides == PK_PROVIDES_ENUM_MIMETYPE) {
++                      search_cmd = g_strdup_printf ("search -qp mimetype(%s)", search);
++              }
+       }
+       if (cmd != NULL && search_cmd)
+@@ -1307,6 +1415,30 @@ backend_destroy (PkBackend *backend)
+ }
+ /**
++ * backend_get_groups:
++ **/
++static PkGroupEnum
++backend_get_groups (PkBackend *backend)
++{
++      return (PK_GROUP_ENUM_ACCESSORIES |
++              PK_GROUP_ENUM_ADMIN_TOOLS |
++              PK_GROUP_ENUM_COMMUNICATION |
++              PK_GROUP_ENUM_EDUCATION |
++              PK_GROUP_ENUM_FONTS |
++              PK_GROUP_ENUM_GAMES |
++              PK_GROUP_ENUM_GRAPHICS |
++              PK_GROUP_ENUM_LOCALIZATION |
++              PK_GROUP_ENUM_MULTIMEDIA |
++              PK_GROUP_ENUM_NETWORK |
++              PK_GROUP_ENUM_OFFICE |
++              PK_GROUP_ENUM_OTHER |
++              PK_GROUP_ENUM_PROGRAMMING |
++              PK_GROUP_ENUM_PUBLISHING |
++              PK_GROUP_ENUM_SERVERS |
++              PK_GROUP_ENUM_SYSTEM);
++}
++
++/**
+  * backend_get_filters:
+  */
+ static PkFilterEnum
+@@ -1398,14 +1530,17 @@ backend_get_details_thread (PkBackend *backend)
+       if (pkg)
+       {
+               struct pkguinf  *pkgu = NULL;
++              PkGroupEnum     group;
+               pkgu = pkg_uinf (pkg);
++              group = pld_group_to_enum (pkg_group (pkg));
++
+               if (pkgu) {
+                       pk_backend_details (backend,
+                                               package_id,
+                                               pkguinf_get (pkgu, PKGUINF_LICENSE),
+-                                              PK_GROUP_ENUM_OTHER,
++                                              group,
+                                               pkguinf_get (pkgu, PKGUINF_DESCRIPTION),
+                                               pkguinf_get (pkgu, PKGUINF_URL),
+                                               pkg->size);
+@@ -1414,7 +1549,7 @@ backend_get_details_thread (PkBackend *backend)
+                       pk_backend_details (backend,
+                                               package_id,
+                                               "",
+-                                              PK_GROUP_ENUM_OTHER,
++                                              group,
+                                               "",
+                                               "",
+                                               pkg->size);
+@@ -2213,12 +2348,26 @@ backend_get_repo_list (PkBackend *backend, PkFilterEnum filters)
+       pk_backend_finished (backend);
+ }
++/**
++ * backend_what_provides:
++ **/
++static void
++backend_what_provides (PkBackend *backend, PkFilterEnum filters, PkProvidesEnum provides, const gchar *search)
++{
++      pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
++      poldek_backend_set_allow_cancel (backend, TRUE, TRUE);
++      pb_error_clean ();
++
++      pk_backend_set_uint (backend, "mode", SEARCH_ENUM_PROVIDES);
++      pk_backend_thread_create (backend, search_package_thread);
++}
++
+ PK_BACKEND_OPTIONS (
+       "poldek",                                       /* description */
+       "Marcin Banasiak <megabajt@pld-linux.org>",     /* author */
+       backend_initalize,                              /* initalize */
+       backend_destroy,                                /* destroy */
+-      NULL,                                           /* get_groups */
++      backend_get_groups,                             /* get_groups */
+       backend_get_filters,                            /* get_filters */
+       backend_get_cancel,                             /* cancel */
+       backend_get_depends,                            /* get_depends */
+@@ -2245,6 +2394,6 @@ PK_BACKEND_OPTIONS (
+       NULL,                                           /* service pack */
+       backend_update_packages,                        /* update_packages */
+       backend_update_system,                          /* update_system */
+-      NULL                                            /* what_provides */
++      backend_what_provides                           /* what_provides */
+ );
+diff --git a/backends/urpmi/.gitignore b/backends/urpmi/.gitignore
+new file mode 100644
+index 0000000..996fb0d
+--- /dev/null
++++ b/backends/urpmi/.gitignore
+@@ -0,0 +1,14 @@
++.deps
++.libs
++Makefile
++Makefile.in
++*.la
++*.lo
++*.loT
++*.o
++*~
++*.gcov
++*.gcda
++*.gcno
++*.out
++
+diff --git a/backends/urpmi/Makefile.am b/backends/urpmi/Makefile.am
+new file mode 100644
+index 0000000..56743a1
+--- /dev/null
++++ b/backends/urpmi/Makefile.am
+@@ -0,0 +1,11 @@
++SUBDIRS = helpers
++plugindir = $(PK_PLUGIN_DIR)
++plugin_LTLIBRARIES = libpk_backend_urpmi.la
++libpk_backend_urpmi_la_SOURCES = pk-backend-urpmi.c
++libpk_backend_urpmi_la_LIBADD = $(PK_PLUGIN_LIBS)
++libpk_backend_urpmi_la_LDFLAGS = -module -avoid-version
++libpk_backend_urpmi_la_CFLAGS = $(PK_PLUGIN_CFLAGS)
++
++clean-local:
++      rm -f *.gcno
++
+diff --git a/backends/urpmi/helpers/.gitignore b/backends/urpmi/helpers/.gitignore
+new file mode 100644
+index 0000000..2f78cf5
+--- /dev/null
++++ b/backends/urpmi/helpers/.gitignore
+@@ -0,0 +1,2 @@
++*.pyc
++
+diff --git a/backends/urpmi/helpers/Makefile.am b/backends/urpmi/helpers/Makefile.am
+new file mode 100644
+index 0000000..88f144e
+--- /dev/null
++++ b/backends/urpmi/helpers/Makefile.am
+@@ -0,0 +1,31 @@
++SUBDIRS = perl_packagekit urpmi_backend
++
++helperdir = $(datadir)/PackageKit/helpers/urpmi
++
++NULL =
++
++dist_helper_DATA =                                            \
++      search-name.pl                                                  \
++      get-details.pl                                                  \
++      get-depends.pl                                                  \
++      get-files.pl                                                            \
++      get-updates.pl                                                  \
++      get-update-detail.pl                            \
++      refresh-cache.pl                                                \
++      install-packages.pl                                     \
++      remove-packages.pl                                      \
++      search-group.pl                                                 \
++      get-packages.pl                                                 \
++      get-requires.pl                                                 \
++      search-details.pl                                               \
++      search-file.pl                                                  \
++      resolve.pl                                                                      \
++      update-packages.pl                                      \
++      $(NULL)
++
++install-data-hook:
++      chmod a+rx $(DESTDIR)$(helperdir)/*.pl
++
++clean-local :
++      rm -f *~
++
+diff --git a/backends/urpmi/helpers/get-depends.pl b/backends/urpmi/helpers/get-depends.pl
+new file mode 100755
+index 0000000..bf936c5
+--- /dev/null
++++ b/backends/urpmi/helpers/get-depends.pl
+@@ -0,0 +1,85 @@
++#!/usr/bin/perl
++
++use strict;
++
++use lib;
++use File::Basename;
++
++BEGIN {
++  push @INC, dirname($0);
++}
++
++use URPM;
++use urpm;
++use urpm::args;
++use urpm::media;
++use urpm::select;
++
++use urpmi_backend::open_db;
++use urpmi_backend::tools;
++
++use perl_packagekit::enums;
++use perl_packagekit::prints;
++
++# Two arguments (filter, package id)
++exit if($#ARGV != 2);
++
++my @filters = split(/;/, $ARGV[0]);
++my @pkgid = split(/;/, $ARGV[1]);
++my $recursive_option = 0;
++$recursive_option = 1 if($ARGV[2] eq "yes");
++
++# Only recursive option is supported
++# So, if user set no tu recursive option, 
++# backend will return error
++if(!$recursive_option) {
++  printf("error\tnot-supported\tOnly recursive option to yes is supported\n");
++  exit;
++}
++
++pk_print_status(PK_STATUS_ENUM_DEP_RESOLVE);
++
++my $urpm = urpm->new_parse_cmdline;
++urpm::media::configure($urpm);
++
++my %requested;
++my @names = (@pkgid[0]);
++my $results = urpm::select::search_packages($urpm, \%requested, \@names,
++  fuzzy => 0,
++  caseinsensitive => 0,
++  all => 0
++);
++
++exit if !$results;
++my @requested_keys = keys %requested;
++my $package_id = pop @requested_keys;
++
++my %resolv_request = ();
++%resolv_request->{$package_id} = 1;
++
++my $empty_db = new URPM;
++my $state = {};
++$urpm->resolve_requested($empty_db,
++  $state,
++  \%resolv_request,
++);
++
++my $db = open_rpm_db();
++$urpm->compute_installed_flags($db);
++
++my %selected = %{$state->{selected}};
++my @selected_keys = keys %selected;
++my @depslist = @{$urpm->{depslist}};
++
++foreach(sort {@depslist[$b]->flag_installed <=> @depslist[$a]->flag_installed} @selected_keys) {
++  my $pkg = @depslist[$_];
++  if($pkg->flag_installed) {
++    next if(grep(/^${\FILTER_NOT_INSTALLED}$/, @filters));
++    pk_print_package(INFO_INSTALLED, get_package_id($pkg), $pkg->summary);
++  }
++  else {
++    next if(grep(/^${\FILTER_INSTALLED}$/, @filters));
++    pk_print_package(INFO_AVAILABLE, get_package_id($pkg), $pkg->summary);
++  }
++}
++
+diff --git a/backends/urpmi/helpers/get-details.pl b/backends/urpmi/helpers/get-details.pl
+new file mode 100755
+index 0000000..3207e9b
+--- /dev/null
++++ b/backends/urpmi/helpers/get-details.pl
+@@ -0,0 +1,48 @@
++#!/usr/bin/perl
++
++use strict;
++
++use lib;
++use File::Basename;
++
++BEGIN {
++  push @INC, dirname($0);
++}
++
++use urpm;
++use urpm::args;
++use urpm::media;
++use urpmi_backend::tools;
++use MDK::Common;
++
++use perl_packagekit::prints;
++
++# One argument (package id)
++exit if($#ARGV != 0);
++
++my $urpm = urpm->new_parse_cmdline;
++urpm::media::configure($urpm);
++
++my $pkg = get_package_by_package_id($urpm, $ARGV[0]);
++
++my $medium = pkg2medium($pkg, $urpm);
++my $xml_info = 'info';
++my $xml_info_file = urpm::media::any_xml_info($urpm, $medium, $xml_info, undef, undef);
++
++if(!$xml_info_file) {
++  pk_print_details(get_package_id($pkg), "N/A", $pkg->group, "N/A", "N/A", 0);
++  exit 0;
++}
++
++require urpm::xml_info;
++require urpm::xml_info_pkg;
++my $name = urpm_name($pkg);
++my %nodes = eval { urpm::xml_info::get_nodes($xml_info, $xml_info_file, [ $name ]) };
++my %xml_info_pkgs;
++put_in_hash($xml_info_pkgs{$name} ||= {}, $nodes{$name});
++my $description = $xml_info_pkgs{$name}{description};
++$description =~ s/\n/;/g;
++$description =~ s/\t/ /g;
++
++pk_print_details(get_package_id($pkg), "N/A", $pkg->group, ensure_utf8($description), "N/A", $pkg->size);
++
+diff --git a/backends/urpmi/helpers/get-files.pl b/backends/urpmi/helpers/get-files.pl
+new file mode 100755
+index 0000000..74ae157
+--- /dev/null
++++ b/backends/urpmi/helpers/get-files.pl
+@@ -0,0 +1,40 @@
++#!/usr/bin/perl
++
++use strict;
++
++use lib;
++use File::Basename;
++
++BEGIN {
++  push @INC, dirname($0);
++}
++
++use urpm;
++use urpm::args;
++use urpm::media;
++use urpmi_backend::tools;
++use MDK::Common;
++
++use perl_packagekit::prints;
++
++# One argument (package id)
++exit if($#ARGV != 0);
++
++
++my $urpm = urpm->new_parse_cmdline;
++urpm::media::configure($urpm);
++
++my $pkg = get_package_by_package_id($urpm, $ARGV[0]);
++
++my $medium = pkg2medium($pkg, $urpm);
++my $xml_info = 'files';
++my $xml_info_file = urpm::media::any_xml_info($urpm, $medium, $xml_info, undef, undef);
++require urpm::xml_info;
++require urpm::xml_info_pkg;
++my $name = urpm_name($pkg);
++my %nodes = eval { urpm::xml_info::get_nodes($xml_info, $xml_info_file, [ $name ]) };
++my %xml_info_pkgs;
++put_in_hash($xml_info_pkgs{$name} ||= {}, $nodes{$name});
++my @files = map { chomp_($_) } split("\n", $xml_info_pkgs{$name}{files});
++
++pk_print_files(get_package_id($pkg), join(';', @files));
+diff --git a/backends/urpmi/helpers/get-packages.pl b/backends/urpmi/helpers/get-packages.pl
+new file mode 100755
+index 0000000..9e3e525
+--- /dev/null
++++ b/backends/urpmi/helpers/get-packages.pl
+@@ -0,0 +1,53 @@
++#!/usr/bin/perl
++
++use strict;
++
++use lib;
++use File::Basename;
++
++BEGIN {
++  push @INC, dirname($0);
++}
++
++use urpm;
++use urpm::media;
++use urpm::args;
++
++use urpmi_backend::open_db;
++use urpmi_backend::tools;
++use urpmi_backend::filters;
++
++use perl_packagekit::enums;
++use perl_packagekit::prints;
++
++# One argument (the filter)
++exit if ($#ARGV != 0);
++my @filters = split(/;/, $ARGV[0]);
++
++my $urpm = urpm->new_parse_cmdline;
++
++urpm::media::configure($urpm);
++
++my $db = open_rpm_db();
++$urpm->compute_installed_flags($db);
++
++# Here we display installed packages
++if(not grep(/^${\FILTER_NOT_INSTALLED}$/, @filters)) {
++  $db->traverse(sub {
++      my ($pkg) = @_;
++      if(filter($pkg, \@filters, {FILTER_DEVELOPMENT => 1, FILTER_GUI => 1})) {
++        pk_print_package(INFO_INSTALLED, get_package_id($pkg), ensure_utf8($pkg->summary));
++      }
++    });
++}
++
++# Here are package which can be installed
++if(not grep(/^${\FILTER_INSTALLED}$/, @filters)) {
++  foreach my $pkg(@{$urpm->{depslist}}) {
++    if($pkg->flag_upgrade) {
++      if(filter($pkg, \@filters, {FILTER_DEVELOPMENT => 1, FILTER_GUI => 1})) {
++        pk_print_package(INFO_AVAILABLE, get_package_id($pkg), ensure_utf8($pkg->summary));
++      }
++    }  
++  }
++}
+diff --git a/backends/urpmi/helpers/get-requires.pl b/backends/urpmi/helpers/get-requires.pl
+new file mode 100755
+index 0000000..0012b2a
+--- /dev/null
++++ b/backends/urpmi/helpers/get-requires.pl
+@@ -0,0 +1,54 @@
++#!/usr/bin/perl
++
++use strict;
++
++use lib;
++use File::Basename;
++
++BEGIN {
++  push @INC, dirname($0);
++}
++
++use urpm;
++use urpm::args;
++use urpm::media;
++use urpm::select;
++use urpmi_backend::tools;
++use urpmi_backend::actions;
++use urpmi_backend::filters;
++use perl_packagekit::enums;
++use perl_packagekit::prints;
++
++# 3 arguments
++# (filter, packageid, and recursive option)
++exit if($#ARGV != 2);
++
++my @filters = split(/;/, $ARGV[0]);
++my $pkgid = $ARGV[1];
++my $recursive_option = 0;
++$recursive_option = 1 if($ARGV[2] eq "yes");
++
++my $urpm = urpm->new_parse_cmdline;
++urpm::media::configure($urpm);
++
++my $pkg = get_package_by_package_id($urpm, $pkgid);
++if(!$pkg) {
++  pk_print_error(PK_ERROR_ENUM_PACKAGE_NOT_FOUND, "Requested package wasn't found");
++  exit;
++}
++# print "Checking requires of the package : ", urpm_name($pkg), "\n";
++pk_print_status(PK_STATUS_ENUM_DEP_RESOLVE);
++my @requires = perform_requires_search($urpm, $pkg, $recursive_option);
++
++foreach(@requires) {
++  if(filter($_, \@filters, { FILTER_GUI => 1, FILTER_DEVELOPMENT => 1 })) {
++    if(package_version_is_installed($_)) {
++      !grep(/^${\FILTER_NOT_INSTALLED}$/, @filters) and pk_print_package(INFO_INSTALLED, get_package_id($_), $_->summary);
++    }
++    else {
++      !grep(/^${\FILTER_INSTALLED}$/, @filters) and pk_print_package(INFO_AVAILABLE, get_package_id($_), $_->summary);
++    }
++  }
++}
++pk_print_status(PK_STATUS_ENUM_FINISHED);
++
+diff --git a/backends/urpmi/helpers/get-update-detail.pl b/backends/urpmi/helpers/get-update-detail.pl
+new file mode 100755
+index 0000000..69ea452
+--- /dev/null
++++ b/backends/urpmi/helpers/get-update-detail.pl
+@@ -0,0 +1,88 @@
++#!/usr/bin/perl
++
++use strict;
++
++use lib;
++use File::Basename;
++
++BEGIN {
++  push @INC, dirname($0);
++}
++
++use urpm;
++use urpm::args;
++use urpm::media;
++use urpm::select;
++use urpmi_backend::tools;
++use urpmi_backend::open_db;
++use perl_packagekit::enums;
++use perl_packagekit::prints;
++use MDK::Common;
++
++# One argument (package id)
++exit if($#ARGV != 0);
++
++my $urpm = urpm->new_parse_cmdline;
++urpm::media::configure($urpm);
++
++my $pkg = get_package_by_package_id($urpm, @ARGV[0]);
++
++if(!$pkg) {
++  pk_print_error(PK_ERROR_ENUM_PACKAGE_NOT_FOUND, "Requested package was not found");
++  exit;
++}
++
++my %requested;
++$requested{$pkg->id} = 1;
++
++if(!find_installed_version($pkg)) {
++  pk_print_error(PK_ERROR_ENUM_PACKAGE_NOT_INSTALLED, "The selected package isn't installed on your system");
++}
++elsif(package_version_is_installed($pkg)) {
++  pk_print_error(PK_ERROR_ENUM_PACKAGE_ALREADY_INSTALLED, "The selected package is already at the latest version");
++}
++else {
++  my $state = {};
++  my $restart = urpm::select::resolve_dependencies($urpm, $state, \%requested);
++  my %selected = %{$state->{selected}};
++  my @ask_unselect = urpm::select::unselected_packages($urpm, $state);
++  my @to_remove = urpm::select::removed_packages($urpm, $state);
++  my @to_install = @{$urpm->{depslist}}[sort { $a <=> $b } keys %{$state->{selected}}]; 
++  my ($src, $binary) = partition { $_->arch eq 'src' } @to_install;
++  @to_install = @$binary;
++  my $updates_descr = urpm::get_updates_description($urpm);
++  my $updesc = $updates_descr->{URPM::pkg2media($urpm->{media}, $pkg)->{name}}{$pkg->name};
++  my $desc;
++  if($updesc) {
++    $desc = $updesc->{pre};
++    $desc =~ s/\n/;/g;
++  }
++
++  my @to_upgrade_pkids;
++  foreach(@to_install) {
++    my $pkid = get_installed_version_pkid($_);
++    push @to_upgrade_pkids, $pkid if $pkid;
++  }
++
++  if($restart) {
++    pk_print_update_detail(get_package_id($pkg),
++      join("^", @to_upgrade_pkids),
++      join("^", map(fullname_to_package_id($_), @to_remove)),
++      "http://qa.mandriva.com",
++      "http://qa.mandriva.com",
++      "http://qa.mandriva.com",
++      PK_RESTART_ENUM_SYSTEM,
++      $desc);
++  }
++  else {
++    pk_print_update_detail(get_package_id($pkg),
++      join("^", @to_upgrade_pkids),
++      join("^", map(fullname_to_package_id($_), @to_remove)),
++      "http://qa.mandriva.com",
++      "http://qa.mandriva.com",
++      "http://qa.mandriva.com",
++      PK_RESTART_ENUM_APPLICATION,
++      $desc);
++  }
++
++}
+diff --git a/backends/urpmi/helpers/get-updates.pl b/backends/urpmi/helpers/get-updates.pl
+new file mode 100755
+index 0000000..02d574c
+--- /dev/null
++++ b/backends/urpmi/helpers/get-updates.pl
+@@ -0,0 +1,46 @@
++#!/usr/bin/perl
++
++use strict;
++
++use lib;
++use File::Basename;
++
++BEGIN {
++  push @INC, dirname($0);
++}
++
++use urpm;
++use urpm::args;
++use urpm::media;
++use urpm::select;
++use MDK::Common;
++use urpmi_backend::tools;
++use perl_packagekit::enums;
++use perl_packagekit::prints;
++
++# On argument (filter)
++exit if($#ARGV != 0);
++# Fix me
++# Filter are to be implemented.
++
++my $urpm = urpm->new_parse_cmdline;
++urpm::media::configure($urpm);
++
++my $state = {};
++my %requested;
++my $restart = urpm::select::resolve_dependencies($urpm, $state, \%requested,
++  auto_select => 1);
++
++my %selected = %{$state->{selected} || {}};
++my @ask_unselect = urpm::select::unselected_packages($urpm, $state);
++my @to_remove = urpm::select::removed_packages($urpm, $state);
++my @to_install = @{$urpm->{depslist}}[sort { $a <=> $b } keys %{$state->{selected}}]; 
++my ($src, $binary) = partition { $_->arch eq 'src' } @to_install;
++@to_install = @$binary;
++  
++foreach(@to_install) {
++  # Fix me
++  # Be default, we set to bugfix info type
++  # Need to be implemented, see urpmq source.
++  pk_print_package(INFO_BUGFIX, get_package_id($_), $_->summary);
++}
+diff --git a/backends/urpmi/helpers/install-packages.pl b/backends/urpmi/helpers/install-packages.pl
+new file mode 100755
+index 0000000..c9cf6c8
+--- /dev/null
++++ b/backends/urpmi/helpers/install-packages.pl
+@@ -0,0 +1,40 @@
++#!/usr/bin/perl
++
++use strict;
++
++use lib;
++use File::Basename;
++
++BEGIN {
++  push @INC, dirname($0);
++}
++
++use urpm;
++use urpm::media;
++use urpm::select;
++
++use urpmi_backend::actions;
++use urpmi_backend::tools;
++
++# One argument (package id)
++exit if($#ARGV != 0);
++
++my @pkg_ids = split(/\|/, pop @ARGV);
++my @names;
++foreach(@pkg_ids) {
++  my @pkg_id = (split(/;/, $_));
++  push @names, $pkg_id[0];
++}
++
++
++my $urpm = urpm->new_parse_cmdline;
++urpm::media::configure($urpm);
++
++my %requested;
++
++urpm::select::search_packages($urpm, \%requested, \@names, 
++  fuzzy => 0, 
++  caseinsensitive => 0,
++  all => 0);
++
++perform_installation($urpm, \%requested);
+diff --git a/backends/urpmi/helpers/perl_packagekit/Makefile.am b/backends/urpmi/helpers/perl_packagekit/Makefile.am
+new file mode 100644
+index 0000000..6ed63b5
+--- /dev/null
++++ b/backends/urpmi/helpers/perl_packagekit/Makefile.am
+@@ -0,0 +1,12 @@
++helperdir = $(datadir)/PackageKit/helpers/urpmi/perl_packagekit/
++
++NULL =
++
++dist_helper_DATA =                                            \
++      enums.pm                                                                                \
++      prints.pm                                                                               \
++      $(NULL)
++
++clean-local :
++      rm -f *~
++
+diff --git a/backends/urpmi/helpers/perl_packagekit/enums.pm b/backends/urpmi/helpers/perl_packagekit/enums.pm
+new file mode 100644
+index 0000000..8dbb4b0
+--- /dev/null
++++ b/backends/urpmi/helpers/perl_packagekit/enums.pm
+@@ -0,0 +1,293 @@
++package perl_packagekit::enums;
++
++use Exporter;
++
++our @ISA = qw(Exporter);
++our @EXPORT = qw(
++  FILTER_BASENAME 
++  FILTER_DEVELOPMENT 
++  FILTER_FREE 
++  FILTER_GUI 
++  FILTER_INSTALLED 
++  FILTER_NEWEST 
++  FILTER_NONE 
++  FILTER_NOT_BASENAME 
++  FILTER_NOT_DEVELOPMENT 
++  FILTER_NOT_FREE 
++  FILTER_NOT_GUI 
++  FILTER_NOT_INSTALLED 
++  FILTER_NOT_NEWEST 
++  FILTER_NOT_SUPPORTED 
++  FILTER_NOT_VISIBLE 
++  FILTER_SUPPORTED 
++  FILTER_UNKNOWN 
++  FILTER_VISIBLE
++  
++  GROUP_ACCESSIBILITY 
++  GROUP_ACCESSORIES 
++  GROUP_ADMIN_TOOLS 
++  GROUP_COMMUNICATION 
++  GROUP_DESKTOP_GNOME 
++  GROUP_DESKTOP_KDE 
++  GROUP_DESKTOP_OTHER 
++  GROUP_DESKTOP_XFCE 
++  GROUP_EDUCATION 
++  GROUP_FONTS 
++  GROUP_GAMES 
++  GROUP_GRAPHICS 
++  GROUP_INTERNET 
++  GROUP_LEGACY 
++  GROUP_LOCALIZATION 
++  GROUP_MAPS 
++  GROUP_MULTIMEDIA 
++  GROUP_NETWORK 
++  GROUP_OFFICE 
++  GROUP_OTHER 
++  GROUP_POWER_MANAGEMENT 
++  GROUP_PROGRAMMING 
++  GROUP_PUBLISHING 
++  GROUP_REPOS 
++  GROUP_SECURITY 
++  GROUP_SERVERS 
++  GROUP_SYSTEM 
++  GROUP_UNKNOWN 
++  GROUP_VIRTUALIZATION 
++  
++  INFO_AVAILABLE 
++  INFO_BLOCKED 
++  INFO_BUGFIX 
++  INFO_CLEANUP 
++  INFO_DOWNLOADING 
++  INFO_ENHANCEMENT 
++  INFO_IMPORTANT 
++  INFO_INSTALLED 
++  INFO_INSTALLING 
++  INFO_LOW 
++  INFO_NORMAL 
++  INFO_OBSOLETING 
++  INFO_REMOVING 
++  INFO_SECURITY 
++  INFO_UNKNOWN 
++  INFO_UPDATING 
++
++  PK_ERROR_ENUM_UNKNOWN 
++  PK_ERROR_ENUM_OOM 
++  PK_ERROR_ENUM_NO_CACHE 
++  PK_ERROR_ENUM_NO_NETWORK 
++  PK_ERROR_ENUM_NOT_SUPPORTED 
++  PK_ERROR_ENUM_INTERNAL_ERROR 
++  PK_ERROR_ENUM_GPG_FAILURE 
++  PK_ERROR_ENUM_FILTER_INVALID 
++  PK_ERROR_ENUM_PACKAGE_ID_INVALID 
++  PK_ERROR_ENUM_TRANSACTION_ERROR 
++  PK_ERROR_ENUM_TRANSACTION_CANCELLED 
++  PK_ERROR_ENUM_PACKAGE_NOT_INSTALLED 
++  PK_ERROR_ENUM_PACKAGE_NOT_FOUND 
++  PK_ERROR_ENUM_PACKAGE_ALREADY_INSTALLED 
++  PK_ERROR_ENUM_PACKAGE_DOWNLOAD_FAILED 
++  PK_ERROR_ENUM_GROUP_NOT_FOUND 
++  PK_ERROR_ENUM_GROUP_LIST_INVALID 
++  PK_ERROR_ENUM_DEP_RESOLUTION_FAILED 
++  PK_ERROR_ENUM_CREATE_THREAD_FAILED 
++  PK_ERROR_ENUM_REPO_NOT_FOUND 
++  PK_ERROR_ENUM_CANNOT_REMOVE_SYSTEM_PACKAGE 
++  PK_ERROR_ENUM_PROCESS_KILL 
++  PK_ERROR_ENUM_FAILED_INITIALIZATION 
++  PK_ERROR_ENUM_FAILED_FINALISE 
++  PK_ERROR_ENUM_FAILED_CONFIG_PARSING 
++  PK_ERROR_ENUM_CANNOT_CANCEL 
++  PK_ERROR_ENUM_CANNOT_GET_LOCK 
++  PK_ERROR_ENUM_NO_PACKAGES_TO_UPDATE 
++  PK_ERROR_ENUM_CANNOT_WRITE_REPO_CONFIG 
++  PK_ERROR_ENUM_LOCAL_INSTALL_FAILED 
++  PK_ERROR_ENUM_BAD_GPG_SIGNATURE 
++  PK_ERROR_ENUM_MISSING_GPG_SIGNATURE 
++  PK_ERROR_ENUM_CANNOT_INSTALL_SOURCE_PACKAGE 
++  PK_ERROR_ENUM_REPO_CONFIGURATION_ERROR 
++  PK_ERROR_ENUM_NO_LICENSE_AGREEMENT 
++  PK_ERROR_ENUM_FILE_CONFLICTS 
++  PK_ERROR_ENUM_REPO_NOT_AVAILABLE 
++  PK_ERROR_ENUM_INVALID_PACKAGE_FILE 
++  PK_ERROR_ENUM_PACKAGE_INSTALL_BLOCKED 
++  
++  PK_RESTART_ENUM_UNKNOWN
++  PK_RESTART_ENUM_NONE
++  PK_RESTART_ENUM_SYSTEM
++  PK_RESTART_ENUM_SESSION
++  PK_RESTART_ENUM_APPLICATION
++  
++  PK_STATUS_ENUM_UNKNOWN 
++  PK_STATUS_ENUM_WAIT 
++  PK_STATUS_ENUM_SETUP 
++  PK_STATUS_ENUM_RUNNING 
++  PK_STATUS_ENUM_QUERY 
++  PK_STATUS_ENUM_INFO 
++  PK_STATUS_ENUM_REFRESH_CACHE 
++  PK_STATUS_ENUM_REMOVE 
++  PK_STATUS_ENUM_DOWNLOAD 
++  PK_STATUS_ENUM_INSTALL 
++  PK_STATUS_ENUM_UPDATE 
++  PK_STATUS_ENUM_CLEANUP 
++  PK_STATUS_ENUM_OBSOLETE 
++  PK_STATUS_ENUM_DEP_RESOLVE 
++  PK_STATUS_ENUM_SIG_CHECK 
++  PK_STATUS_ENUM_ROLLBACK 
++  PK_STATUS_ENUM_TEST_COMMIT 
++  PK_STATUS_ENUM_COMMIT 
++  PK_STATUS_ENUM_REQUEST 
++  PK_STATUS_ENUM_FINISHED 
++  PK_STATUS_ENUM_CANCEL 
++  PK_STATUS_ENUM_DOWNLOAD_REPOSITORY 
++  PK_STATUS_ENUM_DOWNLOAD_PACKAGELIST 
++  PK_STATUS_ENUM_DOWNLOAD_FILELIST 
++  PK_STATUS_ENUM_DOWNLOAD_CHANGELOG 
++  PK_STATUS_ENUM_DOWNLOAD_GROUP 
++  PK_STATUS_ENUM_DOWNLOAD_UPDATEINFO 
++
++  );
++
++use constant {
++  FILTER_BASENAME => "basename",
++  FILTER_DEVELOPMENT => "devel",
++  FILTER_FREE => "free",
++  FILTER_GUI => "gui",
++  FILTER_INSTALLED => "installed",
++  FILTER_NEWEST => "newest",
++  FILTER_NONE => "none",
++  FILTER_NOT_BASENAME => "~basename",
++  FILTER_NOT_DEVELOPMENT => "~devel",
++  FILTER_NOT_FREE => "~free",
++  FILTER_NOT_GUI => "~gui",
++  FILTER_NOT_INSTALLED => "~installed",
++  FILTER_NOT_NEWEST => "~newest",
++  FILTER_NOT_SUPPORTED => "~supported",
++  FILTER_NOT_VISIBLE => "~visible",
++  FILTER_SUPPORTED => "supported",
++  FILTER_UNKNOWN => "unknown",
++  FILTER_VISIBLE => "visible",
++
++  GROUP_ACCESSIBILITY => "accessibility",
++  GROUP_ACCESSORIES => "accessories",
++  GROUP_ADMIN_TOOLS => "admin-tools",
++  GROUP_COMMUNICATION => "communication",
++  GROUP_DESKTOP_GNOME => "desktop-gnome",
++  GROUP_DESKTOP_KDE => "desktop-kde",
++  GROUP_DESKTOP_OTHER => "desktop-other",
++  GROUP_DESKTOP_XFCE => "desktop-xfce",
++  GROUP_EDUCATION => "education",
++  GROUP_FONTS => "fonts",
++  GROUP_GAMES => "games",
++  GROUP_GRAPHICS => "graphics",
++  GROUP_INTERNET => "internet",
++  GROUP_LEGACY => "legacy",
++  GROUP_LOCALIZATION => "localization",
++  GROUP_MAPS => "maps",
++  GROUP_MULTIMEDIA => "multimedia",
++  GROUP_NETWORK => "network",
++  GROUP_OFFICE => "office",
++  GROUP_OTHER => "other",
++  GROUP_POWER_MANAGEMENT => "power-management",
++  GROUP_PROGRAMMING => "programming",
++  GROUP_PUBLISHING => "publishing",
++  GROUP_REPOS => "repos",
++  GROUP_SECURITY => "security",
++  GROUP_SERVERS => "servers",
++  GROUP_SYSTEM => "system",
++  GROUP_UNKNOWN => "unknown",
++  GROUP_VIRTUALIZATION => "virtualization",
++
++  INFO_AVAILABLE => "available",
++  INFO_BLOCKED => "blocked",
++  INFO_BUGFIX => "bugfix",
++  INFO_CLEANUP => "cleanup",
++  INFO_DOWNLOADING => "downloading",
++  INFO_ENHANCEMENT => "enhancement",
++  INFO_IMPORTANT => "important",
++  INFO_INSTALLED => "installed",
++  INFO_INSTALLING => "installing",
++  INFO_LOW => "low",
++  INFO_NORMAL => "normal",
++  INFO_OBSOLETING => "obsoleting",
++  INFO_REMOVING => "removing",
++  INFO_SECURITY => "security",
++  INFO_UNKNOWN => "unknown",
++  INFO_UPDATING => "updating",
++
++  PK_ERROR_ENUM_UNKNOWN => "unknown",
++  PK_ERROR_ENUM_OOM => "out-of-memory",
++  PK_ERROR_ENUM_NO_CACHE => "no-cache",
++  PK_ERROR_ENUM_NO_NETWORK => "no-network",
++  PK_ERROR_ENUM_NOT_SUPPORTED => "not-supported",
++  PK_ERROR_ENUM_INTERNAL_ERROR => "internal-error",
++  PK_ERROR_ENUM_GPG_FAILURE => "gpg-failure",
++  PK_ERROR_ENUM_FILTER_INVALID => "filter-invalid",
++  PK_ERROR_ENUM_PACKAGE_ID_INVALID => "package-id-invalid",
++  PK_ERROR_ENUM_TRANSACTION_ERROR => "transaction-error",
++  PK_ERROR_ENUM_TRANSACTION_CANCELLED => "transaction-cancelled",
++  PK_ERROR_ENUM_PACKAGE_NOT_INSTALLED => "package-not-installed",
++  PK_ERROR_ENUM_PACKAGE_NOT_FOUND => "package-not-found",
++  PK_ERROR_ENUM_PACKAGE_ALREADY_INSTALLED => "package-already-installed",
++  PK_ERROR_ENUM_PACKAGE_DOWNLOAD_FAILED => "package-download-failed",
++  PK_ERROR_ENUM_GROUP_NOT_FOUND => "group-not-found",
++  PK_ERROR_ENUM_GROUP_LIST_INVALID => "group-list-invalid",
++  PK_ERROR_ENUM_DEP_RESOLUTION_FAILED => "dep-resolution-failed",
++  PK_ERROR_ENUM_CREATE_THREAD_FAILED => "create-thread-failed",
++  PK_ERROR_ENUM_REPO_NOT_FOUND => "repo-not-found",
++  PK_ERROR_ENUM_CANNOT_REMOVE_SYSTEM_PACKAGE => "cannot-remove-system-package",
++  PK_ERROR_ENUM_PROCESS_KILL => "process-kill",
++  PK_ERROR_ENUM_FAILED_INITIALIZATION => "failed-initialization",
++  PK_ERROR_ENUM_FAILED_FINALISE => "failed-finalise",
++  PK_ERROR_ENUM_FAILED_CONFIG_PARSING => "failed-config-parsing",
++  PK_ERROR_ENUM_CANNOT_CANCEL => "cannot-cancel",
++  PK_ERROR_ENUM_CANNOT_GET_LOCK => "cannot-get-lock",
++  PK_ERROR_ENUM_NO_PACKAGES_TO_UPDATE => "no-packages-to-update",
++  PK_ERROR_ENUM_CANNOT_WRITE_REPO_CONFIG => "cannot-write-repo-config",
++  PK_ERROR_ENUM_LOCAL_INSTALL_FAILED => "local-install-failed",
++  PK_ERROR_ENUM_BAD_GPG_SIGNATURE => "bad-gpg-signature",
++  PK_ERROR_ENUM_MISSING_GPG_SIGNATURE => "missing-gpg-signature",
++  PK_ERROR_ENUM_CANNOT_INSTALL_SOURCE_PACKAGE => "cannot-install-source-package",
++  PK_ERROR_ENUM_REPO_CONFIGURATION_ERROR => "repo-configuration-error",
++  PK_ERROR_ENUM_NO_LICENSE_AGREEMENT => "no-license-agreement",
++  PK_ERROR_ENUM_FILE_CONFLICTS => "file-conflicts",
++  PK_ERROR_ENUM_REPO_NOT_AVAILABLE => "repo-not-available",
++  PK_ERROR_ENUM_INVALID_PACKAGE_FILE => "invalid-package-file",
++  PK_ERROR_ENUM_PACKAGE_INSTALL_BLOCKED => "package-install-blocked",
++
++  PK_RESTART_ENUM_UNKNOWN => "unknown",
++  PK_RESTART_ENUM_NONE => "none",
++  PK_RESTART_ENUM_SYSTEM => "system",
++  PK_RESTART_ENUM_SESSION => "session",
++  PK_RESTART_ENUM_APPLICATION => "application",
++
++  PK_STATUS_ENUM_UNKNOWN => "unknown",
++  PK_STATUS_ENUM_WAIT => "wait",
++  PK_STATUS_ENUM_SETUP => "setup",
++  PK_STATUS_ENUM_RUNNING => "running",
++  PK_STATUS_ENUM_QUERY => "query",
++  PK_STATUS_ENUM_INFO => "info",
++  PK_STATUS_ENUM_REFRESH_CACHE => "refresh-cache",
++  PK_STATUS_ENUM_REMOVE => "remove",
++  PK_STATUS_ENUM_DOWNLOAD => "download",
++  PK_STATUS_ENUM_INSTALL => "install",
++  PK_STATUS_ENUM_UPDATE => "update",
++  PK_STATUS_ENUM_CLEANUP => "cleanup",
++  PK_STATUS_ENUM_OBSOLETE => "obsolete",
++  PK_STATUS_ENUM_DEP_RESOLVE => "dep-resolve",
++  PK_STATUS_ENUM_SIG_CHECK => "sig-check",
++  PK_STATUS_ENUM_ROLLBACK => "rollback",
++  PK_STATUS_ENUM_TEST_COMMIT => "test-commit",
++  PK_STATUS_ENUM_COMMIT => "commit",
++  PK_STATUS_ENUM_REQUEST => "request",
++  PK_STATUS_ENUM_FINISHED => "finished",
++  PK_STATUS_ENUM_CANCEL => "cancel",
++  PK_STATUS_ENUM_DOWNLOAD_REPOSITORY => "download-repository",
++  PK_STATUS_ENUM_DOWNLOAD_PACKAGELIST => "download-package",
++  PK_STATUS_ENUM_DOWNLOAD_FILELIST => "download-filelist",
++  PK_STATUS_ENUM_DOWNLOAD_CHANGELOG => "download-changelog",
++  PK_STATUS_ENUM_DOWNLOAD_GROUP => "download-group",
++  PK_STATUS_ENUM_DOWNLOAD_UPDATEINFO => "download-updateinfo",
++
++
++};
++
++1;
+diff --git a/backends/urpmi/helpers/perl_packagekit/prints.pm b/backends/urpmi/helpers/perl_packagekit/prints.pm
+new file mode 100644
+index 0000000..7411ca9
+--- /dev/null
++++ b/backends/urpmi/helpers/perl_packagekit/prints.pm
+@@ -0,0 +1,95 @@
++package perl_packagekit::prints;
++
++use Exporter;
++
++our @ISA = qw(Exporter);
++our @EXPORT = qw(
++  pk_print_package
++  pk_print_status
++  pk_print_details
++  pk_print_files
++  pk_print_update_detail
++  pk_print_require_restart
++  pk_print_error
++  pk_print_percentage
++  pk_print_sub_percentage
++  );
++
++sub pk_print_package {
++  # send 'package' signal
++  # @param info: the enumerated INFO_* string
++  # @param id: The package ID name, e.g. openoffice-clipart;2.6.22;ppc64;fedora
++  # @param summary: The package Summary
++  my ($info, $id, $summary) = @_;
++  printf("package\t%s\t%s\t%s\n", $info, $id, $summary);
++}
++
++sub pk_print_status {
++  # send 'status' signal
++  # @param state: STATUS_*
++  my ($status) = @_;
++  printf("status\t%s\n", $status);
++}
++
++sub pk_print_details {
++  # Send 'details' signal
++  # @param id: The package ID name, e.g. openoffice-clipart;2.6.22;ppc64;fedora
++  # @param license: The license of the package
++  # @param group: The enumerated group
++  # @param desc: The multi line package description
++  # @param url: The upstream project homepage
++  # @param bytes: The size of the package, in bytes
++  my ($id, $license, $group, $desc, $url, $bytes) = @_;
++  printf("details\t%s\t%s\t%s\t%s\t%s\t%ld\n", $id, $license, $group, $desc, $url, $bytes);
++}
++
++sub pk_print_files {
++  # Send 'files' signal
++  # @param file_list: List of the files in the package, separated by ';'
++  my ($id, $file_list) = @_;
++  printf("files\t%s\t%s\n", $id, $file_list);
++}
++    
++sub pk_print_update_detail {
++  # Send 'updatedetail' signal
++  # @param id: The package ID name, e.g. openoffice-clipart;2.6.22;ppc64;fedora
++  # @param updates:
++  # @param obsoletes:
++  # @param vendor_url:
++  # @param bugzilla_url:
++  # @param cve_url:
++  # @param restart:
++  # @param update_text:
++  my ($id, $updates, $obsoletes, $vendor_url, $bugzilla_url, $cve_url, $restart, $update_text) = @_;
++  printf("updatedetail\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n", $id, $updates, $obsoletes, $vendor_url, $bugzilla_url, $cve_url, $restart, $update_text);
++}
++    
++sub pk_print_require_restart {
++  # Send 'requirerestart' signal
++  # @param restart_type: RESTART_SYSTEM, RESTART_APPLICATION,RESTART_SESSION
++  # @param details: Optional details about the restart
++  my ($restart_type, $details) = @_;
++  printf("requirerestart\t%s\t%s\n", $restart_type, $details);
++}
++    
++sub pk_print_error {
++  # send 'error'
++  # @param err: Error Type ERROR_*
++  # @param description: Error description
++  # @param exit: exit application with rc=1, if true
++  my ($err, $description) = @_;
++  printf("error\t%s\t%s\n", $err, $description);
++  exit if($exit);
++}
++
++sub pk_print_percentage {
++  my ($percentage) = @_;
++  printf("percentage\t%i\n", $percentage);
++}
++
++sub pk_print_sub_percentage {
++  my ($sub_percentage) = @_;
++  printf("subpercentage\t%i\n", $sub_percentage);
++}
++
++1;
+diff --git a/backends/urpmi/helpers/refresh-cache.pl b/backends/urpmi/helpers/refresh-cache.pl
+new file mode 100755
+index 0000000..555a8b8
+--- /dev/null
++++ b/backends/urpmi/helpers/refresh-cache.pl
+@@ -0,0 +1,33 @@
++#!/usr/bin/perl
++
++use strict;
++
++use lib;
++use File::Basename;
++
++BEGIN {
++  push @INC, dirname($0);
++}
++
++use urpm;
++use urpm::media;
++use urpm::select;
++use urpm::args;
++use urpmi_backend::actions;
++
++# No arguments
++exit if($#ARGV != -1);
++
++#my $urpm = urpm->new_parse_cmdline;
++my $urpm = urpm->new_parse_cmdline;
++my $urpmi_lock = urpm::lock::urpmi_db($urpm, 'exclusive', wait => 0);
++urpm::media::read_config($urpm);
++
++my @entries = map { $_->{name} } @{$urpm->{media}};
++@entries == 0 and die N("nothing to update (use urpmi.addmedia to add a media)\n");
++
++my %options = ( all => 1 );
++
++my $ok = urpm::media::update_media($urpm, %options, 
++  quiet => 0);
++exit($ok ? 0 : 1);
+diff --git a/backends/urpmi/helpers/remove-packages.pl b/backends/urpmi/helpers/remove-packages.pl
+new file mode 100755
+index 0000000..3be38ea
+--- /dev/null
++++ b/backends/urpmi/helpers/remove-packages.pl
+@@ -0,0 +1,90 @@
++#!/usr/bin/perl
++
++use strict;
++
++use lib;
++use File::Basename;
++
++BEGIN {
++  push @INC, dirname($0);
++}
++
++use urpm;
++use urpm::args;
++use urpm::media;
++use urpm::select;
++use urpm::install;
++use urpmi_backend::tools;
++use perl_packagekit::enums;
++use perl_packagekit::prints;
++
++my $notfound = 0;
++my @breaking_pkgs = ();
++my $allowdeps_option = 0;
++my @pkgid;
++my $state = {};
++my $notfound_callback = sub {
++  $notfound = 1;
++};
++
++# This script call only be called with two arguments (allow_deps (yes/no) and a package id)
++exit if($#ARGV != 1);
++
++my $urpm = urpm->new_parse_cmdline;
++my $urpmi_lock = urpm::lock::urpmi_db($urpm, 'exclusive', wait => 1);
++urpm::media::configure($urpm);
++
++$allowdeps_option = 1 if($ARGV[0] eq "yes");
++
++my @pkg_ids = split(/\|/, pop @ARGV);
++my @names;
++foreach(@pkg_ids) {
++  my @pkg_id = (split(/;/, $_));
++  push @names, $pkg_id[0];
++}
++
++pk_print_status(PK_STATUS_ENUM_DEP_RESOLVE);
++
++my @to_remove = urpm::select::find_packages_to_remove($urpm,
++  $state,
++  \@names,
++  callback_notfound => $notfound_callback,
++  callback_fuzzy => $notfound_callback,
++  callback_base => sub {
++    my $urpm = shift @_;
++    push @breaking_pkgs, @_;
++  }
++);
++
++if($notfound) {
++  # printf("Error: package %s not found\n", $pkgid[0]);
++  pk_print_error(PK_ERROR_ENUM_PACKAGE_NOT_INSTALLED, "Selected package isn't installed on your system");
++}
++elsif(@breaking_pkgs) {
++  # printf("Error: These packages will break your system = \n\t%s\n", join("\n\t", @breaking_pkgs));
++  pk_print_error(PK_ERROR_ENUM_CANNOT_REMOVE_SYSTEM_PACKAGE, "Removing selected packages will break your system");
++}
++else {
++  # printf("It's ok, I will remove %s NOW !\n", $pkgid[0]);
++  # printf("To remove list = \n\t%s\n", join("\n\t", @to_remove));
++  if(!$allowdeps_option && $#to_remove > 1) {
++    pk_print_error(PK_ERROR_ENUM_TRANSACTION_ERROR, "Packages can't be removed because dependencies remove is forbidden");
++    # printf("I can't remove, because you don't allow deps remove :'(\n");
++  }
++  else {
++    # printf("Let's go for removing ...\n");
++    pk_print_status(PK_STATUS_ENUM_REMOVE);
++    urpm::install::install($urpm,
++      \@to_remove, {}, {},
++      callback_report_uninst => sub {
++        my @return = split(/ /, $_[0]);
++        # printf("Package\tRemoving\t%s\n", fullname_to_package_id($return[$#return]));
++        pk_print_package(INFO_REMOVING, fullname_to_package_id($return[$#return]), "");
++      }
++    );
++  }
++}
++
++$urpmi_lock->unlock;
++
++pk_print_status(PK_STATUS_ENUM_FINISHED);
+diff --git a/backends/urpmi/helpers/resolve.pl b/backends/urpmi/helpers/resolve.pl
+new file mode 100755
+index 0000000..32e0866
+--- /dev/null
++++ b/backends/urpmi/helpers/resolve.pl
+@@ -0,0 +1,64 @@
++#!/usr/bin/perl
++
++use strict;
++
++use lib;
++use File::Basename;
++
++BEGIN {
++  push @INC, dirname($0);
++}
++
++use urpm;
++use urpm::args;
++use urpm::media;
++use urpmi_backend::open_db;
++use urpmi_backend::tools;
++use urpmi_backend::filters;
++use perl_packagekit::enums;
++use perl_packagekit::prints;
++
++# Two arguments (filter and package name)
++exit if ($#ARGV != 1);
++my @filters = split(/;/, $ARGV[0]);
++my $search_term = $ARGV[1];
++
++my $urpm = urpm->new_parse_cmdline;
++urpm::media::configure($urpm);
++
++my @names = ( $search_term );
++my %requested;
++my $result = urpm::select::search_packages($urpm, \%requested, \@names, 
++  fuzzy => 0, 
++  caseinsensitive => 0,
++  all => 0
++);
++
++if($result) {
++  my @requested_keys = keys %requested;
++  my $db = open_rpm_db();
++  $urpm->compute_installed_flags($db);
++  my $pkg = @{$urpm->{depslist}}[$requested_keys[0]];
++
++  # We exit the script if found package does not match with
++  # specified filters
++  if(!filter($pkg, \@filters, {FILTER_DEVELOPMENT => 1, FILTER_GUI => 1})) {
++    exit;
++  }
++  if($pkg->version."-".$pkg->release eq find_installed_version($pkg)) {
++    if(grep(/^${\FILTER_NOT_INSTALLED}$/, @filters)) {
++      exit;
++    }
++    pk_print_package(INFO_INSTALLED, get_package_id($pkg), $pkg->summary);
++  }
++  else {
++    if(grep(/^${\FILTER_INSTALLED}$/, @filters)) {
++      exit;
++    }
++    pk_print_package(INFO_AVAILABLE, get_package_id($pkg), $pkg->summary);
++  }
++}
++else {
++  pk_print_error(PK_ERROR_ENUM_PACKAGE_NOT_FOUND, "Can't find any package for the specified name");
++}
++
+diff --git a/backends/urpmi/helpers/search-details.pl b/backends/urpmi/helpers/search-details.pl
+new file mode 100755
+index 0000000..3081abe
+--- /dev/null
++++ b/backends/urpmi/helpers/search-details.pl
+@@ -0,0 +1,57 @@
++#!/usr/bin/perl
++
++use strict;
++
++use lib;
++use File::Basename;
++
++BEGIN {
++  push @INC, dirname($0);
++}
++
++use urpm;
++use urpm::media;
++use urpm::args;
++
++use urpmi_backend::open_db;
++use urpmi_backend::tools;
++use urpmi_backend::filters;
++
++use perl_packagekit::enums;
++use perl_packagekit::prints;
++
++# Two arguments (filterand search term)
++exit if ($#ARGV != 1);
++my @filters = split(/;/, $ARGV[0]);
++my $search_term = $ARGV[1];
++
++my $urpm = urpm->new_parse_cmdline;
++urpm::media::configure($urpm);
++
++my $db = open_rpm_db();
++$urpm->compute_installed_flags($db);
++
++# Here we display installed packages
++if(not grep(/^${\FILTER_NOT_INSTALLED}$/, @filters)) {
++  $db->traverse(sub {
++      my ($pkg) = @_;
++      if(filter($pkg, \@filters, {FILTER_DEVELOPMENT => 1, FILTER_GUI => 1})) {
++        if($pkg->name =~ /$search_term/ || $pkg->summary =~ /$search_term/ || $pkg->url =~ /$search_term/) {
++          pk_print_package(INFO_INSTALLED, get_package_id($pkg), ensure_utf8($pkg->summary));
++        }
++      }
++    });
++}
++
++# Here are package which can be installed
++if(not grep(/^${\FILTER_INSTALLED}$/, @filters)) {
++  foreach my $pkg(@{$urpm->{depslist}}) {
++    if($pkg->flag_upgrade) {
++      if(filter($pkg, \@filters, {FILTER_DEVELOPMENT => 1, FILTER_GUI => 1})) {
++        if($pkg->name =~ /$search_term/ || $pkg->summary =~ /$search_term/ || $pkg->url =~ /$search_term/) {
++          pk_print_package(INFO_AVAILABLE, get_package_id($pkg), ensure_utf8($pkg->summary));
++        }
++      }
++    }  
++  }
++}
+diff --git a/backends/urpmi/helpers/search-file.pl b/backends/urpmi/helpers/search-file.pl
+new file mode 100755
+index 0000000..03d348e
+--- /dev/null
++++ b/backends/urpmi/helpers/search-file.pl
+@@ -0,0 +1,48 @@
++#!/usr/bin/perl
++
++use strict;
++
++use lib;
++use File::Basename;
++
++BEGIN {
++  push @INC, dirname($0);
++}
++
++use urpm;
++use urpm::media;
++
++use urpmi_backend::actions;
++use urpmi_backend::filters;
++use urpmi_backend::tools;
++use perl_packagekit::prints;
++use perl_packagekit::enums;
++
++# Two arguments (filter and search term)
++exit if ($#ARGV != 1);
++my @filters = split(/;/, $ARGV[0]);
++my $search_term = $ARGV[1];
++
++my $urpm = urpm->new_parse_cmdline;
++urpm::media::configure($urpm);
++
++my %requested;
++
++pk_print_status(PK_STATUS_ENUM_QUERY);
++
++perform_file_search($urpm, \%requested, $search_term, fuzzy => 1);
++
++foreach(keys %requested) {
++  my $p = @{$urpm->{depslist}}[$_];
++  if(filter($p, \@filters, { FILTER_INSTALLED => 1, FILTER_DEVELOPMENT=> 1, FILTER_GUI => 1})) {
++    my $version = find_installed_version($p);
++    if($version eq $p->version."-".$p->release) {
++      pk_print_package(INFO_INSTALLED, get_package_id($p), ensure_utf8($p->summary));
++    }
++    else {
++      pk_print_package(INFO_AVAILABLE, get_package_id($p), ensure_utf8($p->summary));
++    }
++  }
++}
++
++pk_print_status(PK_STATUS_ENUM_FINISHED);
+diff --git a/backends/urpmi/helpers/search-group.pl b/backends/urpmi/helpers/search-group.pl
+new file mode 100755
+index 0000000..e5b7b92
+--- /dev/null
++++ b/backends/urpmi/helpers/search-group.pl
+@@ -0,0 +1,58 @@
++#!/usr/bin/perl
++
++use strict;
++
++use lib;
++use File::Basename;
++
++BEGIN {
++  push @INC, dirname($0);
++}
++
++use urpm;
++use urpm::media;
++use urpm::args;
++
++use urpmi_backend::open_db;
++use urpmi_backend::tools;
++use urpmi_backend::filters;
++use urpmi_backend::groups;
++
++use perl_packagekit::enums;
++use perl_packagekit::prints;
++
++# Two arguments (filter and packagekit group)
++exit if ($#ARGV != 1);
++my @filters = split(/;/, $ARGV[0]);
++my $pk_group = $ARGV[1];
++
++my $urpm = urpm->new_parse_cmdline;
++urpm::media::configure($urpm);
++
++my $db = open_rpm_db();
++$urpm->compute_installed_flags($db);
++
++# Here we display installed packages
++if(not grep(/^${\FILTER_NOT_INSTALLED}$/, @filters)) {
++  $db->traverse(sub {
++      my ($pkg) = @_;
++      if(filter($pkg, \@filters, {FILTER_DEVELOPMENT => 1, FILTER_GUI => 1})) {
++        if(package_belongs_to_pk_group($pkg, $pk_group)) {
++          pk_print_package(INFO_INSTALLED, get_package_id($pkg), ensure_utf8($pkg->summary));
++        }
++      }
++    });
++}
++
++# Here are package which can be installed
++if(not grep(/^${\FILTER_INSTALLED}$/, @filters)) {
++  foreach my $pkg(@{$urpm->{depslist}}) {
++    if($pkg->flag_upgrade) {
++      if(filter($pkg, \@filters, {FILTER_DEVELOPMENT => 1, FILTER_GUI => 1})) {
++        if(package_belongs_to_pk_group($pkg, $pk_group)) {
++          pk_print_package(INFO_AVAILABLE, get_package_id($pkg), ensure_utf8($pkg->summary));
++        }
++      }
++    }  
++  }
++}
+diff --git a/backends/urpmi/helpers/search-name.pl b/backends/urpmi/helpers/search-name.pl
+new file mode 100755
+index 0000000..383921f
+--- /dev/null
++++ b/backends/urpmi/helpers/search-name.pl
+@@ -0,0 +1,64 @@
++#!/usr/bin/perl
++
++use strict;
++
++use lib;
++use File::Basename;
++
++BEGIN {
++  push @INC, dirname($0);
++}
++
++use urpm;
++use urpm::media;
++use urpm::args;
++
++use urpmi_backend::open_db;
++use urpmi_backend::tools;
++use urpmi_backend::filters;
++
++use perl_packagekit::enums;
++use perl_packagekit::prints;
++
++# Two arguments (filter, search term)
++exit if ($#ARGV != 1);
++
++my @filters = split(/;/, $ARGV[0]);
++my $search_term = $ARGV[1];
++
++my $basename_option = FILTER_BASENAME;
++$basename_option = grep(/$basename_option/, @filters);
++
++my $urpm = urpm->new_parse_cmdline;
++
++urpm::media::configure($urpm);
++
++my $db = open_rpm_db();
++$urpm->compute_installed_flags($db);
++
++# Here we display installed packages
++if(not grep(/^${\FILTER_NOT_INSTALLED}$/, @filters)) {
++  $db->traverse(sub {
++      my ($pkg) = @_;
++      if(filter($pkg, \@filters, {FILTER_DEVELOPMENT => 1, FILTER_GUI => 1})) {
++        if( (!$basename_option && $pkg->name =~ /$search_term/)
++          || $pkg->name =~ /^$search_term$/ ) {
++          pk_print_package(INFO_INSTALLED, get_package_id($pkg), ensure_utf8($pkg->summary));
++        }
++      }
++    });
++}
++
++# Here are packages which can be installed
++if(grep(/^${\FILTER_INSTALLED}$/, @filters)) {
++  exit 0;
++}
++
++foreach my $pkg(@{$urpm->{depslist}}) {
++  if($pkg->flag_upgrade && filter($pkg, \@filters, {FILTER_DEVELOPMENT => 1, FILTER_GUI => 1})) {
++    if( (!$basename_option && $pkg->name =~ /$search_term/)
++      || $pkg->name =~ /^$search_term$/ ) {
++      pk_print_package(INFO_AVAILABLE, get_package_id($pkg), ensure_utf8($pkg->summary));
++    }
++  }
++}
+diff --git a/backends/urpmi/helpers/update-packages.pl b/backends/urpmi/helpers/update-packages.pl
+new file mode 100755
+index 0000000..88274bc
+--- /dev/null
++++ b/backends/urpmi/helpers/update-packages.pl
+@@ -0,0 +1,50 @@
++#!/usr/bin/perl
++
++use strict;
++
++use lib;
++use File::Basename;
++
++BEGIN {
++  push @INC, dirname($0);
++}
++
++use urpm;
++use urpm::media;
++use urpm::select;
++use urpm::args;
++use urpmi_backend::tools;
++use urpmi_backend::open_db;
++use urpmi_backend::actions;
++
++# This script call only be called with one argument (the package id)
++exit if($#ARGV != 0);
++
++my @names;
++foreach(split(/\|/, $ARGV[0])) {
++  my @pkgid = split(/;/, $_);
++  push @names, $pkgid[0];
++}
++
++my $urpm = urpm->new_parse_cmdline;
++urpm::media::configure($urpm);
++
++my $db = open_rpm_db();
++$urpm->compute_installed_flags($db);
++
++my %requested;
++
++my @depslist = @{$urpm->{depslist}};
++my $pkg = undef;
++foreach my $depslistpkg (@depslist) {
++  foreach my $name (@names) {
++    if($depslistpkg->name =~ /^$name$/ && $depslistpkg->flag_upgrade) {
++      $requested{$depslistpkg->id} = 1;
++      goto tonext;
++    }
++  }
++  tonext:
++}
++
++perform_installation($urpm, \%requested);
++
+diff --git a/backends/urpmi/helpers/urpmi_backend/Makefile.am b/backends/urpmi/helpers/urpmi_backend/Makefile.am
+new file mode 100644
+index 0000000..3eb8280
+--- /dev/null
++++ b/backends/urpmi/helpers/urpmi_backend/Makefile.am
+@@ -0,0 +1,15 @@
++helperdir = $(datadir)/PackageKit/helpers/urpmi/urpmi_backend/
++
++NULL =
++
++dist_helper_DATA =                                            \
++      actions.pm                                                                      \
++      filters.pm                                                                      \
++      groups.pm                                                                               \
++      open_db.pm                                                                      \
++      tools.pm                                                                                \
++      $(NULL)
++
++clean-local :
++      rm -f *~
++
+diff --git a/backends/urpmi/helpers/urpmi_backend/actions.pm b/backends/urpmi/helpers/urpmi_backend/actions.pm
+new file mode 100644
+index 0000000..a01b893
+--- /dev/null
++++ b/backends/urpmi/helpers/urpmi_backend/actions.pm
+@@ -0,0 +1,297 @@
++package urpmi_backend::actions;
++
++use strict;
++
++use urpm;
++use urpm::args;
++use urpm::msg;
++use urpm::main_loop;
++use urpm::lock;
++use urpmi_backend::tools;
++use urpmi_backend::open_db;
++use MDK::Common;
++use perl_packagekit::enums;
++use perl_packagekit::prints;
++
++use Exporter;
++our @ISA = qw(Exporter);
++our @EXPORT = qw(
++  perform_installation 
++  perform_file_search 
++  perform_requires_search
++);
++
++sub perform_installation {
++  my ($urpm, $requested, %options) = @_;
++  my $state = {};
++  my $restart;
++  my $no_remove = 0;
++
++  # Here we lock urpmi & rpm databases
++  # In third argument we can specified if the script must wait until urpmi or rpm
++  # databases are locked
++  my $lock = urpm::lock::urpmi_db($urpm, undef, wait => 0);
++  my $rpm_lock = urpm::lock::rpm_db($urpm, 'exclusive');
++
++  pk_print_status(PK_STATUS_ENUM_DEP_RESOLVE);
++
++  $restart = urpm::select::resolve_dependencies($urpm, $state, $requested, auto_select => $options{auto_select});
++  my %selected = %{$state->{selected} || {}};
++
++  print "Dependencies = \n\t";
++  print join("\n\t", map(@{$urpm->{depslist}}[$_]->name, keys %selected)), "\n";
++
++  # Here we have packages which cannot be installed because of dependencies
++  my @unselected_uninstalled = @{$state->{unselected_uninstalled} || []};
++  if(@unselected_uninstalled) {
++    my $list = join "\n", map { $_->name . '-' . $_->version . '-' . $_->release  } @unselected_uninstalled;
++  }
++  # Fix me !
++  # Display warning (With pk enum?) which warning the user
++  # that the following packages can't be installed because they depend
++  # on packages that are older than the installed ones (copy/paste from
++  # the diplayed message in urpmi)
++
++  # Here we have packages which cannot be installed
++  my @ask_unselect = urpm::select::unselected_packages($urpm, $state);
++  if (@ask_unselect) {
++    my $list = urpm::select::translate_why_unselected($urpm, $state, @ask_unselect);
++  }
++  # Fix me !
++  # Display warning (With pk enum?) which warning the user
++  # that the following packages can't be installed (copy/paste from
++  # the diplayed message in urpmi)
++
++  my @ask_remove = urpm::select::removed_packages($urpm, $state);
++  if(@ask_remove) {
++    my $db = urpm::db_open_or_die($urpm, $urpm->{root});
++    urpm::select::find_removed_from_basesystem($urpm, $db, $state, sub {
++        my $urpm = shift @_;
++        foreach (@_) {
++          # Fix me 
++          # Someting like that. With a clean pk error enum.
++          # printf ("removing package %s will break your system", $_);
++        }
++        @_ and $no_remove = 1;
++      });
++    my $list = urpm::select::translate_why_removed($urpm, $state, @ask_remove);
++    if($no_remove) {
++      # Fix me
++      # Display message to prevent that the installation cannot continue because some
++      # packages has to be removed for others to be upgraded.
++      exit 0;
++    }
++    # Else, it's ok.
++    # Here we can display $list, which describe packages which has to be removed for
++    # others to be upgraded.
++    printf("Following package(s) will be removed for others to be upgraded:\n%s\n", $list);
++  }
++
++  # sorted by medium for format_selected_packages
++  my @to_install = @{$urpm->{depslist}}[sort { $a <=> $b } keys %{$state->{selected}}]; 
++  my ($src, $binary) = partition { $_->arch eq 'src' } @to_install;
++  # With packagekit, we will never install src packages.
++  @to_install = @$binary;
++
++  print "\@to_install debug : \n\t";
++  print join("\n\t", map(urpm_name($_), @to_install)), "\n";
++
++  my $nb_to_install = $#to_install + 1;
++  my $percentage = 0;
++
++  $urpm->{nb_install} = @to_install;
++  # For debug issue, we will display sizes
++  my ($size, $filesize) = $urpm->selected_size_filesize($state);
++  printf("%s of additional disk space will be used.\n", formatXiB($size));
++  printf("%s of packages will be retrieved.\n", formatXiB($filesize));
++
++  my $callback_inst = sub {
++    my ($urpm, $type, $id, $subtype, $amount, $total) = @_;
++    my $pkg = defined $id ? $urpm->{depslist}[$id] : undef;
++    if ($subtype eq 'start') {
++      if ($type eq 'trans') {
++        print "Preparing packages installation ...\n";
++      pk_print_status(PK_STATUS_ENUM_INSTALL);
++      } 
++      elsif (defined $pkg) {
++        printf("Installing package %s ...\n", $pkg->name);
++      pk_print_package(INFO_INSTALLING, get_package_id($pkg), $pkg->summary);
++      }
++    } 
++    elsif ($subtype eq 'progress') {
++      print "($type) Progress : total = ", $total, " ; amount/total = ", $amount/$total, " ; amount = ", $amount, "\n";
++      if($type eq "inst") {
++        pk_print_percentage($percentage + ($amount/$total)*(100/$nb_to_install));
++        if(($amount/$total) == 1) {
++          $percentage = $percentage + ($amount/$total)*(100/$nb_to_install);
++        }
++      }
++    }
++  };
++
++  # Now, the script will call the urpmi main loop to make installation
++  my $exit_code = urpm::main_loop::run($urpm, $state, undef, \@ask_unselect, $requested, {
++      inst => $callback_inst,
++      trans => $callback_inst,
++      trans_log => sub {
++        my ($mode, $file, $percent, $total, $eta, $speed) = @_;
++        # Transfer log need to be improved.
++        if($mode eq "progress") {
++          pk_print_status(PK_STATUS_ENUM_DOWNLOAD);
++        }
++        print "Install current mode = ", $mode, "\n";
++      },
++      bad_signature => sub {
++        # Here we display a message (with PK enum) to warn the user
++        # about a bad signature, then we exit
++        exit 1;
++      },
++      ask_yes_or_no => sub {
++        # Return 1 = Return Yes
++        return 1;
++      },
++      need_restart => sub {
++        my ($need_restart_formatted) = @_;
++        print "$_\n" foreach values %$need_restart_formatted;
++      },
++      completed => sub {
++        undef $lock;
++        undef $rpm_lock;
++      pk_print_status(PK_STATUS_ENUM_FINISHED);
++      },
++      post_download => sub {
++        # Fix me !
++        # At this point, we need to refuse cancel action
++      },
++    }
++  );
++}
++
++sub perform_file_search {
++  my ($urpm, $requested, $search_term, %options) = @_;
++  my $db = open_rpm_db();
++  $urpm->compute_installed_flags($db);
++
++  my $xml_info = 'files';
++  my %result_hash;
++
++  # - For each medium, we browse the xml info file,
++  # while looking for files which matched with the
++  # search term given in argument. We store results 
++  # in a hash.
++  foreach my $medium (urpm::media::non_ignored_media($urpm)) {
++    my $xml_info_file = urpm::media::any_xml_info($urpm, $medium, ( "files", "summary" ), undef, undef);
++    $xml_info_file or next;
++    require urpm::xml_info;
++    require urpm::xml_info_pkg;
++    my $F = urpm::xml_info::open_lzma($xml_info_file);
++    my $fn;
++    local $_;
++    while (<$F>) {
++      if (m!^<!) {
++        ($fn) = /fn="(.*)"/;
++      } 
++      elsif ( (!$options{'fuzzy'} && $_ =~ /^$search_term$/)
++        || ($options{'fuzzy'} && $_ =~ /$search_term/) ) {
++        # Fix me : Replace with pk error enum.
++        # $fn or $urpm->{fatal}("fast algorithm is broken, please report a bug");
++        my $pkg = urpm::xml_info_pkg->new({ fn => $fn });
++        $result_hash{$pkg->name} = $pkg;
++      }
++    }
++  }
++
++  # - In order to get package summaries, we need to
++  # use the search package method from perl-URPM 
++  # which return Package type on which we can call
++  # methods to create the printing output.
++  # (It's about the same code as search-name.pl)
++  my @names = keys %result_hash;
++
++  urpm::select::search_packages($urpm, $requested, \@names, 
++    fuzzy => 0,
++    caseinsensitive => 0,
++    all => 0,);
++}
++
++sub perform_requires_search {
++
++  my ($urpm, $pkg, $recursive_option) = @_;
++
++  my (@properties, %requires, %properties, $dep);
++  my %requested;
++  urpm::select::search_packages($urpm, 
++    \%requested, [ $pkg->name ], 
++    use_provides => 0,
++    fuzzy => 0,
++    all => 0
++  );
++  @properties = keys %requested;
++  my $state = {};
++
++  foreach my $pkg (@{$urpm->{depslist}}) {
++    foreach ($pkg->requires_nosense) {
++      $requires{$_}{$pkg->id} = undef;
++    }
++  }
++
++  while (defined ($dep = shift @properties)) {
++    my $packages = $urpm->find_candidate_packages($dep);
++    foreach (values %$packages) {
++      my ($best_requested, $best);
++      foreach (@$_) {
++        if ($best_requested || exists $requested{$_->id}) {
++          if ($best_requested && $best_requested != $_) {
++            $_->compare_pkg($best_requested) > 0 and $best_requested = $_;
++          } else {
++            $best_requested = $_;
++          }
++        } elsif ($best && $best != $_) {
++          $_->compare_pkg($best) > 0 and $best = $_;
++        } else {
++          $best = $_;
++        }
++      }
++
++      my $pkg = $best_requested || $best or next;
++      exists $state->{selected}{$pkg->id} and next;
++      $state->{selected}{$pkg->id} = undef;
++
++      next if !$requested{$dep} && !$recursive_option;
++
++      #- for all provides of package, look up what is requiring them.
++      foreach ($pkg->provides) {
++        if (my ($n, $s) = /^([^\s\[]*)(?:\[\*\])?\[?([^\s\]]*\s*[^\s\]]*)/) {
++          if (my @l = grep { $_ ne $pkg->name } map { $_->name } $urpm->packages_providing($n)) {
++            #- If another package provides this requirement,
++            #- then don't bother finding stuff that needs it as it will be invalid
++            # $urpm->{log}(sprintf "skipping package(s) requiring %s via %s, since %s is also provided by %s", $pkg->name, $n, $n, join(' ', @l));
++            next;
++          }
++
++          foreach (map { $urpm->{depslist}[$_] }
++            grep { ! exists $state->{selected}{$_} && ! exists $properties{$_} }
++            keys %{$requires{$n} || {}}) {
++            if (grep { URPM::ranges_overlap("$n $s", $_) } $_->requires) {
++              push @properties, $_->id;
++              # $urpm->{debug} and $urpm->{debug}(sprintf "adding package %s (requires %s%s)", $_->name, $pkg->name, $n eq $pkg->name ? '' : " via $n");
++              $properties{$_->id} = undef;
++            }
++          }
++        }
++      }
++    }
++  }
++
++  my @depslist = @{$urpm->{depslist}};
++  my @requires = ();
++  foreach(@depslist) {
++    my $pkgid = $_->id;
++    if(grep(/^$pkgid$/, keys %{$state->{selected}})) {
++      push @requires, $_;
++    }
++  }
++
++  @requires;
++
++}
+diff --git a/backends/urpmi/helpers/urpmi_backend/filters.pm b/backends/urpmi/helpers/urpmi_backend/filters.pm
+new file mode 100644
+index 0000000..2c2f13a
+--- /dev/null
++++ b/backends/urpmi/helpers/urpmi_backend/filters.pm
+@@ -0,0 +1,78 @@
++package urpmi_backend::filters;
++
++use MDK::Common;
++use perl_packagekit::enums;
++use urpmi_backend::tools;
++
++use Exporter;
++our @ISA = qw(Exporter);
++our @EXPORT = qw(filter);
++
++my @gui_pkgs = map { chomp; $_ } cat_('/usr/share/rpmdrake/gui.lst');
++
++sub filter {
++  my ($pkg, $filters, $enabled_filters) = @_;
++
++  my %e_filters = %{$enabled_filters};
++
++  foreach my $filter (@{$filters}) {
++    if($filter eq FILTER_INSTALLED || $filter eq FILTER_NOT_INSTALLED) {
++      if($e_filters{FILTER_INSTALLED}) {
++        return 0 if not filter_installed($pkg, $filter);
++      }
++    }
++    elsif($filter eq FILTER_DEVELOPMENT || $filter eq FILTER_NOT_DEVELOPMENT) {
++      if($e_filters{FILTER_DEVELOPMENT}) {
++        return 0 if not filter_devel($pkg, $filter);
++      }
++    }
++    elsif($filter eq FILTER_GUI || $filter eq FILTER_NOT_GUI) {
++      if($e_filters{FILTER_GUI}) {
++        return 0 if not filter_gui($pkg, $filter);
++      }
++    }
++  }
++  return 1;
++}
++
++sub filter_installed {
++  my ($pkg, $filter) = @_;
++  my $installed;
++  $installed = 1 if(find_installed_version($pkg));
++  if($filter eq FILTER_INSTALLED && $installed) {
++    return 1;
++  }
++  if($filter eq FILTER_NOT_INSTALLED && !$installed) {
++    return 1;
++  }
++  return 0;
++}
++
++sub filter_devel {
++  my ($pkg, $filter) = @_;
++  my $pkgname = $pkg->name;
++  my $devel = ($pkgname =~ /-devel$/);
++  if($filter eq FILTER_DEVELOPMENT && $devel) {
++    return 1;
++  }
++  if($filter eq FILTER_NOT_DEVELOPMENT && !$devel) {
++    return 1;
++  }
++  return 0;
++}
++
++sub filter_gui {
++  my ($pkg, $filter) = @_;
++  my $pkgname = $pkg->name;
++  my $gui = member($pkgname, @gui_pkgs);
++
++  if($filter eq FILTER_NOT_GUI && !$gui) {
++    return 1;
++  }
++  if($filter eq FILTER_GUI && $gui) {
++    return 1;
++  }
++  return 0;
++}
++
++1;
+diff --git a/backends/urpmi/helpers/urpmi_backend/groups.pm b/backends/urpmi/helpers/urpmi_backend/groups.pm
+new file mode 100644
+index 0000000..d377ab2
+--- /dev/null
++++ b/backends/urpmi/helpers/urpmi_backend/groups.pm
+@@ -0,0 +1,129 @@
++package urpmi_backend::groups;
++
++use strict;
++
++use perl_packagekit::enums;
++use Exporter;
++
++our @ISA = qw(Exporter);
++our @EXPORT = qw(
++  MDV_GROUPS
++  get_mdv_groups 
++  get_pk_group 
++  package_belongs_to_pk_group
++);
++
++use constant MDV_GROUPS => {
++    'Accessibility' => GROUP_ACCESSIBILITY,
++    'Archiving/Backup' => GROUP_OTHER,
++    'Archiving/Cd burning' => GROUP_MULTIMEDIA,
++    'Archiving/Compression' => GROUP_ACCESSORIES,
++    'Archiving/Other' => GROUP_OTHER,
++    'Books/Computer books' => GROUP_OTHER,
++    'Books/Faqs' => GROUP_OTHER,
++    'Books/Howtos' => GROUP_OTHER,
++    'Books/Literature' => GROUP_OTHER,
++    'Books/Other' => GROUP_OTHER,
++    'Communications' => GROUP_COMMUNICATION,
++    'Databases' => GROUP_PROGRAMMING,
++    'Development/C' => GROUP_PROGRAMMING,
++    'Development/C++' => GROUP_PROGRAMMING,
++    'Development/Databases' => GROUP_PROGRAMMING,
++    'Development/GNOME and GTK+' => GROUP_PROGRAMMING,
++    'Development/Java' => GROUP_PROGRAMMING,
++    'Development/KDE and Qt' => GROUP_PROGRAMMING,
++    'Development/Kernel' => GROUP_PROGRAMMING,
++    'Development/Other' => GROUP_PROGRAMMING,
++    'Development/Perl' => GROUP_PROGRAMMING,
++    'Development/PHP' => GROUP_PROGRAMMING,
++    'Development/Python' => GROUP_PROGRAMMING,
++    'Development/Ruby' => GROUP_PROGRAMMING,
++    'Development/X11' => GROUP_PROGRAMMING,
++    'Editors' => GROUP_ACCESSORIES,
++    'Education' => GROUP_EDUCATION,
++    'Emulators' => GROUP_VIRTUALIZATION,
++    'File tools' => GROUP_ACCESSORIES,
++    'Games/Adventure' => GROUP_GAMES,
++    'Games/Arcade' => GROUP_GAMES,
++    'Games/Boards' => GROUP_GAMES,
++    'Games/Cards' => GROUP_GAMES,
++    'Games/Other' => GROUP_GAMES,
++    'Games/Puzzles' => GROUP_GAMES,
++    'Games/Sports' => GROUP_GAMES,
++    'Games/Strategy' => GROUP_GAMES,
++    'Graphical desktop/Enlightenment' => GROUP_DESKTOP_OTHER,
++    'Graphical desktop/FVWM based' => GROUP_DESKTOP_OTHER,
++    'Graphical desktop/GNOME' => GROUP_DESKTOP_GNOME,
++    'Graphical desktop/Icewm' => GROUP_DESKTOP_OTHER,
++    'Graphical desktop/KDE' => GROUP_DESKTOP_KDE,
++    'Graphical desktop/Other' => GROUP_DESKTOP_OTHER,
++    'Graphical desktop/Sawfish' => GROUP_DESKTOP_OTHER,
++    'Graphical desktop/WindowMaker' => GROUP_DESKTOP_OTHER,
++    'Graphical desktop/Xfce' => GROUP_DESKTOP_XFCE,
++    'Graphics' => GROUP_GRAPHICS,
++    'Monitoring' => GROUP_NETWORK,
++    'Networking/Chat' => GROUP_INTERNET,
++    'Networking/File transfer' =>  GROUP_INTERNET,
++    'Networking/IRC' => GROUP_INTERNET,
++    'Networking/Instant messaging' => GROUP_INTERNET,
++    'Networking/Mail' => GROUP_INTERNET,
++    'Networking/News' => GROUP_INTERNET,
++    'Networking/Other' => GROUP_INTERNET,
++    'Networking/Remote access' => GROUP_INTERNET,
++    'Networking/WWW' => GROUP_INTERNET,
++    'Office' => GROUP_OFFICE,
++    'Publishing' => GROUP_PUBLISHING,
++    'Sciences/Astronomy' => GROUP_OTHER,
++    'Sciences/Biology' => GROUP_OTHER,
++    'Sciences/Chemistry' => GROUP_OTHER,
++    'Sciences/Computer science' => GROUP_OTHER,
++    'Sciences/Geosciences' => GROUP_OTHER,
++    'Sciences/Mathematics' => GROUP_OTHER,
++    'Sciences/Other' => GROUP_OTHER,
++    'Sciences/Physics' => GROUP_OTHER,
++    'Shells' => GROUP_SYSTEM,
++    'Sound' => GROUP_MULTIMEDIA,
++    'System/Base' => GROUP_SYSTEM,
++    'System/Cluster' => GROUP_SYSTEM,
++    'System/Configuration/Boot and Init' => GROUP_SYSTEM,
++    'System/Configuration/Hardware' => GROUP_SYSTEM,
++    'System/Configuration/Networking' => GROUP_SYSTEM,
++    'System/Configuration/Other' => GROUP_SYSTEM,
++    'System/Configuration/Packaging' => GROUP_SYSTEM,
++    'System/Configuration/Printing' => GROUP_SYSTEM,
++    'System/Fonts/Console' => GROUP_FONTS,
++    'System/Fonts/True type' => GROUP_FONTS,
++    'System/Fonts/Type1' => GROUP_FONTS,
++    'System/Fonts/X11 bitmap' => GROUP_FONTS,
++    'System/Internationalization' => GROUP_LOCALIZATION,
++    'System/Kernel and hardware' => GROUP_SYSTEM,
++    'System/Libraries' => GROUP_SYSTEM,
++    'System/Printing' => GROUP_SYSTEM,
++    'System/Servers' => GROUP_SYSTEM,
++    'System/X11' => GROUP_SYSTEM,
++    'Terminals' => GROUP_SYSTEM,
++    'Text tools' => GROUP_ACCESSORIES,
++    'Toys' => GROUP_GAMES,
++    'Video' => GROUP_MULTIMEDIA
++  };
++
++sub get_mdv_groups {
++  my ($pk_group) = @_;
++  my @groups = ();
++  foreach(keys %{(MDV_GROUPS)}) {
++    if(%{(MDV_GROUPS)}->{$_} eq $pk_group) {
++      push @groups, $_;
++    }
++  }
++  return @groups;
++}
++
++sub package_belongs_to_pk_group {
++  my ($pkg, $pk_group) = @_;
++  my @groups = get_mdv_groups($pk_group);
++  my $pkg_group = $pkg->group;
++  return grep(/$pkg_group/, @groups);
++}
++
++1;
++
+diff --git a/backends/urpmi/helpers/urpmi_backend/open_db.pm b/backends/urpmi/helpers/urpmi_backend/open_db.pm
+new file mode 100644
+index 0000000..795edc6
+--- /dev/null
++++ b/backends/urpmi/helpers/urpmi_backend/open_db.pm
+@@ -0,0 +1,48 @@
++package urpmi_backend::open_db;
++
++use strict;
++
++use MDK::Common;
++
++use urpm;
++use urpm::media;
++use urpm::select;
++
++use URPM;
++
++use Exporter;
++our @ISA = qw(Exporter);
++our @EXPORT = qw(fast_open_urpmi_db open_urpmi_db open_rpm_db);
++
++# Note that most part of this perl module
++# is extracted from Rpmdrake
++
++sub fast_open_urpmi_db() {
++    my $urpm = urpm->new;
++    $urpm->get_global_options;
++    urpm::media::read_config($urpm);
++    $urpm;
++}
++
++sub open_urpmi_db {
++    my (%urpmi_options) = @_;
++    my $urpm = fast_open_urpmi_db();
++    my $media = ''; # See Rpmdrake source code for more information.
++
++    my $searchmedia = $urpmi_options{update} ? undef : join(',', get_inactive_backport_media($urpm));
++    $urpm->{lock} = urpm::lock::urpmi_db($urpm, undef, wait => $urpm->{options}{wait_lock});
++    my $previous = ''; # Same as $media above.
++    urpm::select::set_priority_upgrade_option($urpm, (ref $previous ? join(',', @$previous) : ()));
++    urpm::media::configure($urpm, media => $media, if_($searchmedia, searchmedia => $searchmedia), %urpmi_options);
++    $urpm;
++}
++
++sub get_inactive_backport_media {
++    my ($urpm) = @_;
++    map { $_->{name} } grep { $_->{ignore} && $_->{name} =~ /backport/i } @{$urpm->{media}};
++}
++
++sub open_rpm_db {
++  URPM::DB::open() or die "Couldn't open RPM DB";
++}
++
+diff --git a/backends/urpmi/helpers/urpmi_backend/tools.pm b/backends/urpmi/helpers/urpmi_backend/tools.pm
+new file mode 100644
+index 0000000..e078134
+--- /dev/null
++++ b/backends/urpmi/helpers/urpmi_backend/tools.pm
+@@ -0,0 +1,151 @@
++package urpmi_backend::tools;
++
++use strict;
++
++use URPM;
++use urpmi_backend::open_db;
++
++use Exporter;
++our @ISA = qw(Exporter);
++our @EXPORT = qw(
++  get_update_medias 
++  rpm_description 
++  urpm_name 
++  find_installed_version 
++  get_package_id 
++  ensure_utf8 
++  pkg2medium 
++  fullname_to_package_id
++  get_package_by_package_id
++  package_version_is_installed
++  get_package_upgrade
++  get_installed_version
++  get_installed_version_pkid
++);
++
++sub get_update_medias {
++  my ($urpm) = @_;
++  grep { !$_->{ignore} && $_->{update} } @{$urpm->{media}};
++}
++
++sub rpm_description {
++    my ($description) = @_;
++    ensure_utf8($description);
++    my ($t, $tmp);
++    foreach (split "\n", $description) {
++  s/^\s*//;
++        if (/^$/ || /^\s*(-|\*|\+|o)\s/) {
++            $t || $tmp and $t .= "$tmp\n";
++            $tmp = $_;
++        } else {
++            $tmp = ($tmp ? "$tmp " : ($t && "\n") . $tmp) . $_;
++        }
++    }
++    "$t$tmp\n";
++}
++
++sub urpm_name {
++    return '?-?-?.?' unless ref $_[0];
++    my ($name, $version, $release, $arch) = $_[0]->fullname;
++    "$name-$version-$release.$arch";
++}
++
++sub ensure_utf8 {
++    my ($s) = @_;
++    require Encode;
++    Encode::_utf8_on($s); #- this is done on the copy
++    if (!Encode::is_utf8($s, 1)) {
++        Encode::_utf8_off($_[0]);
++        Encode::from_to($_[0], 'iso-8859-15', 'utf8'); # most probable
++    }
++    Encode::_utf8_on($_[0]); #- now we know it is valid utf8
++    $_[0];
++}
++
++sub find_installed_version {
++  my ($p) = @_;
++  my @version;
++  URPM::DB::open()->traverse_tag('name', [ $p->name ], sub { push @version, $_[0]->version . '-' . $_[0]->release });
++  @version ? join(',', sort @version) : "";
++}
++
++sub get_package_id {
++  my ($pkg) = @_;
++  return $pkg->name.";".$pkg->version."-".$pkg->release.";".$pkg->arch.";mandriva";
++}
++
++sub pkg2medium {
++  my ($p, $urpm) = @_;
++  return if !ref $p;
++  return { name => N("None (installed)") } if !$p->id; # if installed
++  URPM::pkg2media($urpm->{media}, $p) || undef;
++}
++
++sub fullname_to_package_id {
++  # fullname, ie 'xeyes-1.0.1-5mdv2008.1.i586'
++  my ($pkg_string) = @_;
++  chomp($pkg_string);
++  $pkg_string =~ /^(.*)-([^-]*)-([^-]*)\.([^\.]*)$/;
++  my %pkg = (
++    name => $1,
++    version => $2,
++    release => $3,
++    arch => $4
++  );
++  return $pkg{name}.";".$pkg{version}."-".$pkg{release}.";".$pkg{arch}.";mandriva";
++}
++
++sub get_package_by_package_id {
++  my ($urpm, $package_id) = @_;
++  my @depslist = @{$urpm->{depslist}};
++  foreach(@depslist) {
++    if(get_package_id($_) eq $package_id) {
++      return $_;
++    }
++  }
++  return;
++}
++
++sub package_version_is_installed {
++  my ($pkg) = @_;
++  return $pkg->version."-".$pkg->release eq find_installed_version($pkg);
++}
++
++sub get_package_upgrade {
++  my ($urpm, $pkg) = @_;
++  my $db = open_rpm_db();
++  $urpm->compute_installed_flags($db);
++  my @depslist = @{$urpm->{depslist}};
++  my $pkgname = $pkg->name;
++  foreach(@depslist) {
++    if($_->name =~ /^$pkgname$/ && $_->flag_upgrade) {
++      return $_;
++    }
++  }
++}
++
++sub get_installed_version {
++  my ($urpm, $pkg) = @_;
++  my @depslist = @{$urpm->{depslist}};
++  my $pkgname = $pkg->name;
++  foreach $_ (@depslist) {
++    if($_->name =~ /^$pkgname$/ && package_version_is_installed($_)) {
++      return $_;
++    }
++  }
++  return;
++}
++
++sub get_installed_version_pkid {
++  my ($pkg) = @_;
++  my $pkgname = $pkg->name;
++  my $db = open_rpm_db();
++  my $installed_pkid;
++  $db->traverse(sub {
++      my ($pkg) = @_;
++      if($pkg->name =~ /^$pkgname$/) {
++        $installed_pkid = get_package_id($pkg);
++      }
++    });
++  return $installed_pkid;
++}
+diff --git a/backends/urpmi/pk-backend-urpmi.c b/backends/urpmi/pk-backend-urpmi.c
+new file mode 100644
+index 0000000..e7b56a7
+--- /dev/null
++++ b/backends/urpmi/pk-backend-urpmi.c
+@@ -0,0 +1,355 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
++ *
++ * Copyright (C) 2007-2008 Richard Hughes <richard@hughsie.com>
++ *
++ * Licensed under the GNU General Public License Version 2
++ *
++ * 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 2 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, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++#include <pk-backend.h>
++#include <pk-backend-spawn.h>
++#include <pk-package-ids.h>
++
++static PkBackendSpawn *spawn;
++
++/**
++ * backend_initialize:
++ * This should only be run once per backend load, i.e. not every transaction
++ */
++static void
++backend_initialize (PkBackend *backend)
++{
++      pk_debug ("FILTER: initialize");
++      spawn = pk_backend_spawn_new ();
++      pk_backend_spawn_set_name (spawn, "urpmi");
++}
++
++/**
++ * backend_destroy:
++ * This should only be run once per backend load, i.e. not every transaction
++ */
++static void
++backend_destroy (PkBackend *backend)
++{
++      pk_debug ("FILTER: destroy");
++      g_object_unref (spawn);
++}
++
++/**
++ * backend_get_groups:
++ */
++static PkGroupEnum
++backend_get_groups (PkBackend *backend)
++{
++  return(PK_GROUP_ENUM_UNKNOWN |
++  PK_GROUP_ENUM_ACCESSIBILITY |
++  PK_GROUP_ENUM_ACCESSORIES |
++  PK_GROUP_ENUM_EDUCATION |
++  PK_GROUP_ENUM_GAMES |
++  PK_GROUP_ENUM_GRAPHICS |
++  PK_GROUP_ENUM_INTERNET |
++  PK_GROUP_ENUM_OFFICE |
++  PK_GROUP_ENUM_OTHER |
++  PK_GROUP_ENUM_PROGRAMMING |
++  PK_GROUP_ENUM_MULTIMEDIA |
++  PK_GROUP_ENUM_SYSTEM |
++  PK_GROUP_ENUM_DESKTOP_GNOME |
++  PK_GROUP_ENUM_DESKTOP_KDE |
++  PK_GROUP_ENUM_DESKTOP_XFCE |
++  PK_GROUP_ENUM_DESKTOP_OTHER |
++  PK_GROUP_ENUM_PUBLISHING |
++  PK_GROUP_ENUM_SERVERS |
++  PK_GROUP_ENUM_FONTS |
++  PK_GROUP_ENUM_ADMIN_TOOLS |
++  PK_GROUP_ENUM_LEGACY |
++  PK_GROUP_ENUM_LOCALIZATION |
++  PK_GROUP_ENUM_VIRTUALIZATION |
++  PK_GROUP_ENUM_POWER_MANAGEMENT |
++  PK_GROUP_ENUM_SECURITY |
++  PK_GROUP_ENUM_COMMUNICATION |
++  PK_GROUP_ENUM_NETWORK |
++  PK_GROUP_ENUM_MAPS |
++  PK_GROUP_ENUM_REPOS);
++}
++
++/**
++ * backend_get_filters:
++ */
++static PkFilterEnum
++backend_get_filters (PkBackend *backend)
++{
++      return (PK_FILTER_ENUM_GUI |
++              PK_FILTER_ENUM_INSTALLED |
++              PK_FILTER_ENUM_DEVELOPMENT);
++}
++
++/**
++ * pk_backend_bool_to_text:
++ */
++static const gchar *
++pk_backend_bool_to_text (gboolean value)
++{
++      if (value == TRUE) {
++              return "yes";
++      }
++      return "no";
++}
++
++
++/**
++ * pk_backend_search_name:
++ */
++static void
++backend_search_name (PkBackend *backend, PkFilterEnum filters, const gchar *search)
++{
++      gchar *filters_text;
++      filters_text = pk_filter_enums_to_text (filters);
++      pk_backend_spawn_helper (spawn, "search-name.pl", filters_text, search, NULL);
++      g_free (filters_text);
++}
++
++/**
++ * backend_get_details:
++ */
++static void
++backend_get_details (PkBackend *backend, const gchar *package_id)
++{
++      pk_backend_spawn_helper (spawn, "get-details.pl", package_id, NULL);
++}
++
++/**
++ * backend_get_files:
++ */
++static void
++backend_get_files (PkBackend *backend, const gchar *package_id)
++{
++      pk_backend_spawn_helper (spawn, "get-files.pl", package_id, NULL);
++}
++
++/**
++ * backend_get_depends:
++ */
++static void
++backend_get_depends (PkBackend *backend, PkFilterEnum filters, const gchar *package_id, gboolean recursive)
++{
++      gchar *filters_text;
++      filters_text = pk_filter_enums_to_text (filters);
++      pk_backend_spawn_helper (spawn, "get-depends.pl", filters_text, package_id, pk_backend_bool_to_text (recursive), NULL);
++      g_free (filters_text);
++}
++
++/**
++ * backend_get_updates:
++ */
++static void
++backend_get_updates (PkBackend *backend, PkFilterEnum filters)
++{
++      gchar *filters_text;
++      filters_text = pk_filter_enums_to_text (filters);
++      pk_backend_spawn_helper (spawn, "get-updates.pl", filters_text, NULL);
++      g_free (filters_text);
++}
++
++/**
++ * backend_get_update_detail:
++ */
++static void
++backend_get_update_detail (PkBackend *backend, const gchar *package_id)
++{
++      pk_backend_spawn_helper (spawn, "get-update-detail.pl", package_id, NULL);
++}
++
++/**
++ * backend_refresh_cache:
++ */
++static void
++backend_refresh_cache (PkBackend *backend, gboolean force)
++{
++      /* check network state */
++      if (!pk_backend_is_online (backend)) {
++              pk_backend_error_code (backend, PK_ERROR_ENUM_NO_NETWORK, "Cannot refresh cache whilst offline");
++              pk_backend_finished (backend);
++              return;
++      }
++
++      pk_backend_spawn_helper (spawn, "refresh-cache.pl", NULL);
++}
++
++/**
++ * backend_install_packages:
++ */
++static void
++backend_install_packages (PkBackend *backend, gchar **package_ids)
++{
++      gchar *package_ids_temp;
++
++      /* check network state */
++      if (!pk_backend_is_online (backend)) {
++              pk_backend_error_code (backend, PK_ERROR_ENUM_NO_NETWORK, "Cannot install when offline");
++              pk_backend_finished (backend);
++              return;
++      }
++
++      /* send the complete list as stdin */
++      package_ids_temp = pk_package_ids_to_text (package_ids, "|");
++      pk_backend_spawn_helper (spawn, "install-packages.pl", package_ids_temp, NULL);
++      g_free (package_ids_temp);
++}
++
++/**
++ * pk_backend_remove_packages:
++ */
++static void
++backend_remove_packages (PkBackend *backend, gchar **package_ids, gboolean allow_deps, gboolean autoremove)
++{
++      gchar *package_ids_temp;
++
++      /* send the complete list as stdin */
++      package_ids_temp = pk_package_ids_to_text (package_ids, "|");
++      pk_backend_spawn_helper (spawn, "remove-packages.pl", pk_backend_bool_to_text (allow_deps), package_ids_temp, NULL);
++      g_free (package_ids_temp);
++}
++
++/**
++ * pk_backend_search_group:
++ */
++static void
++backend_search_group (PkBackend *backend, PkFilterEnum filters, const gchar *search)
++{
++      gchar *filters_text;
++      filters_text = pk_filter_enums_to_text (filters);
++      pk_backend_spawn_helper (spawn, "search-group.pl", filters_text, search, NULL);
++      g_free (filters_text);
++}
++
++/**
++ * backend_get_packages:
++ */
++static void
++backend_get_packages (PkBackend *backend, PkFilterEnum filters)
++{
++      gchar *filters_text;
++      filters_text = pk_filter_enums_to_text (filters);
++      pk_backend_spawn_helper (spawn, "get-packages.pl", filters_text, NULL);
++      g_free (filters_text);
++}
++
++/**
++ * backend_get_requires:
++ */
++static void
++backend_get_requires (PkBackend *backend, PkFilterEnum filters, const gchar *package_id, gboolean recursive)
++{
++      gchar *filters_text;
++      filters_text = pk_filter_enums_to_text (filters);
++      pk_backend_spawn_helper (spawn, "get-requires.pl", filters_text, package_id, pk_backend_bool_to_text (recursive), NULL);
++      g_free (filters_text);
++}
++
++/**
++ * pk_backend_search_details:
++ */
++static void
++backend_search_details (PkBackend *backend, PkFilterEnum filters, const gchar *search)
++{
++      gchar *filters_text;
++      filters_text = pk_filter_enums_to_text (filters);
++      pk_backend_spawn_helper (spawn, "search-details.pl", filters_text, search, NULL);
++      g_free (filters_text);
++}
++
++/**
++ * pk_backend_search_file:
++ */
++static void
++backend_search_file (PkBackend *backend, PkFilterEnum filters, const gchar *search)
++{
++      gchar *filters_text;
++      filters_text = pk_filter_enums_to_text (filters);
++      pk_backend_spawn_helper (spawn, "search-file.pl", filters_text, search, NULL);
++      g_free (filters_text);
++}
++
++/**
++ * pk_backend_resolve:
++ */
++static void
++backend_resolve (PkBackend *backend, PkFilterEnum filters, const gchar *package_id)
++{
++      gchar *filters_text;
++      filters_text = pk_filter_enums_to_text (filters);
++      pk_backend_spawn_helper (spawn, "resolve.pl", filters_text, package_id, NULL);
++      g_free (filters_text);
++}
++
++/**
++ * pk_backend_update_packages:
++ */
++static void
++backend_update_packages (PkBackend *backend, gchar **package_ids)
++{
++      gchar *package_ids_temp;
++
++
++      /* check network state */
++      if (!pk_backend_is_online (backend)) {
++              pk_backend_error_code (backend, PK_ERROR_ENUM_NO_NETWORK, "Cannot install when offline");
++              pk_backend_finished (backend);
++              return;
++      }
++
++      /* send the complete list as stdin */
++      package_ids_temp = pk_package_ids_to_text (package_ids, "|");
++      pk_backend_spawn_helper (spawn, "update-packages.pl", package_ids_temp, NULL);
++      g_free (package_ids_temp);
++}
++
++
++PK_BACKEND_OPTIONS (
++      "URPMI",                                        /* description */
++      "Aurelien Lefebvre <alefebvre@mandriva.com>",   /* author */
++      backend_initialize,                     /* initalize */
++      backend_destroy,                        /* destroy */
++      backend_get_groups,                     /* get_groups */
++      backend_get_filters,                    /* get_filters */
++      NULL,                           /* cancel */
++      backend_get_depends,                    /* get_depends */
++      backend_get_details,                    /* get_details */
++      backend_get_files,                      /* get_files */
++      backend_get_packages,                   /* get_packages */
++      NULL,                   /* get_repo_list */
++      backend_get_requires,                   /* get_requires */
++      backend_get_update_detail,              /* get_update_detail */
++      backend_get_updates,                    /* get_updates */
++      NULL,                   /* install_files */
++      backend_install_packages,               /* install_packages */
++      NULL,           /* install_signature */
++      backend_refresh_cache,                  /* refresh_cache */
++      backend_remove_packages,                /* remove_packages */
++      NULL,                   /* repo_enable */
++      NULL,                   /* repo_set_data */
++      backend_resolve,                        /* resolve */
++      NULL,                                   /* rollback */
++      backend_search_details,                 /* search_details */
++      backend_search_file,                    /* search_file */
++      backend_search_group,                   /* search_group */
++      backend_search_name,                    /* search_name */
++      NULL,                                   /* service_pack */
++      backend_update_packages,                /* update_packages */
++      NULL,                   /* update_system */
++      NULL                    /* what_provides */
++);
++
+diff --git a/backends/yum/helpers/yumBackend.py b/backends/yum/helpers/yumBackend.py
+index 5b2da8f..d70d8dc 100644
+--- a/backends/yum/helpers/yumBackend.py
++++ b/backends/yum/helpers/yumBackend.py
+@@ -901,14 +901,16 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+             if pkg and not inst:
+                 repo = self.yumbase.repos.getRepo(pkg.repoid)
+                 if not already_warned and not repo.gpgcheck:
+-                    self.message(MESSAGE_WARNING,"The package %s was installed untrusted from %s." % (pkg.name, repo))
++                    self.message(MESSAGE_WARNING,"The untrusted package %s will be installed from %s." % (pkg.name, repo))
+                     already_warned = True
+                 txmbr = self.yumbase.install(name=pkg.name)
+                 txmbrs.extend(txmbr)
++            if inst:
++                self.error(ERROR_PACKAGE_ALREADY_INSTALLED,"The package %s is already installed", pkg.name)
+         if txmbrs:
+             self._runYumTransaction()
+         else:
+-            self.error(ERROR_PACKAGE_ALREADY_INSTALLED,"The package is already installed")
++            self.error(ERROR_PACKAGE_ALREADY_INSTALLED,"The packages failed to be installed")
+     def _checkForNewer(self,po):
+         pkgs = self.yumbase.pkgSack.returnNewestByName(name=po.name)
+@@ -927,6 +929,10 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+             if inst_file.endswith('.src.rpm'):
+                 self.error(ERROR_CANNOT_INSTALL_SOURCE_PACKAGE,'Backend will not install a src rpm file')
+                 return
++        for inst_file in inst_files:
++            if not inst_file.endswith('.rpm'):
++                self.error(ERROR_INVALID_PACKAGE_FILE,'Only rpm packages are supported')
++                return
+         self._check_init()
+         self.allow_cancel(False);
+         self.percentage(0)
+@@ -1056,8 +1062,11 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+     def _format_msgs(self,msgs):
+         if isinstance(msgs,basestring):
+-            msgs = msgs.split('\n')
+-        return ";".join(msgs)
++             msgs = msgs.split('\n')
++        text = ";".join(msgs)
++        text = text.replace("Missing Dependency: ","")
++        text = text.replace(" (installed)","")
++        return text
+     def _runYumTransaction(self,removedeps=None):
+         '''
+@@ -1092,16 +1101,19 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+                 if not keyData:
+                     self.error(ERROR_BAD_GPG_SIGNATURE,
+                                "GPG key not imported, and no GPG information was found.")
+-
+                 id = self._pkg_to_id(keyData['po'])
++                fingerprint = keyData['fingerprint']
++                hex_fingerprint = "%02x" * len(fingerprint) % tuple(map(ord, fingerprint))
++                # Borrowed from http://mail.python.org/pipermail/python-list/2000-September/053490.html
++
+                 self.repo_signature_required(id,
+                                              keyData['po'].repoid,
+-                                             keyData['keyurl'],
++                                             keyData['keyurl'].replace("file://",""),
+                                              keyData['userid'],
+                                              keyData['hexkeyid'],
+-                                             keyData['fingerprint'],
+-                                             keyData['timestamp'],
+-                                             'GPG')
++                                             hex_fingerprint,
++                                             time.ctime(keyData['timestamp']),
++                                             'gpg')
+                 self.error(ERROR_GPG_FAILURE,"GPG key %s required" % keyData['hexkeyid'])
+             except yum.Errors.YumBaseError,ye:
+                 message = self._format_msgs(ye.value)
+@@ -1110,7 +1122,7 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+                 else:
+                     self.error(ERROR_TRANSACTION_ERROR,message)
+-    def remove(self,allowdep,package):
++    def remove_packages(self,allowdep,package):
+         '''
+         Implement the {backend}-remove functionality
+         Needed to be implemented in a sub class
+@@ -1394,6 +1406,10 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+                     typ = ref['type']
+                     href = ref['href']
+                     title = ref['title'] or ""
++
++                    # Description can sometimes have ';' in them, and we use that as the delimiter
++                    title = title.replace(";",",")
++
+                     if href:
+                         if typ in ('bugzilla','cve'):
+                             urls[typ].append("%s;%s" % (href,title))
+@@ -1555,11 +1571,7 @@ class DownloadCallback(BaseMeter):
+         '''
+         Get the name of the package being downloaded
+         '''
+-        if self.text and type(self.text) == type(""):
+-            name = self.text
+-        else:
+-            name = self.basename
+-        return name
++        return self.basename
+     def updateProgress(self,name,frac,fread,ftime):
+         '''
+diff --git a/backends/yum2/helpers/yumDBUSBackend.py b/backends/yum2/helpers/yumDBUSBackend.py
+index 29f5b03..a708a0c 100755
+--- a/backends/yum2/helpers/yumDBUSBackend.py
++++ b/backends/yum2/helpers/yumDBUSBackend.py
+@@ -823,15 +823,24 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+         self.PercentageChanged(0)
+         self.StatusChanged(STATUS_RUNNING)
+-        pkg,inst = self._findPackage(package)
+-        if pkg:
++        txmbrs = []
++        already_warned = False
++        for package in packages:
++            pkg,inst = self._findPackage(package)
++            if pkg and not inst:
++                repo = self.yumbase.repos.getRepo(pkg.repoid)
++                if not already_warned and not repo.gpgcheck:
++                    self.message(MESSAGE_WARNING,"The untrusted package %s will be installed from %s." % (pkg.name, repo))
++                    already_warned = True
++                txmbr = self.yumbase.install(name=pkg.name)
++                txmbrs.extend(txmbr)
+             if inst:
+                 self._unlock_yum()
+-                self.ErrorCode(ERROR_PACKAGE_ALREADY_INSTALLED,'Package already installed')
++                self.ErrorCode(ERROR_PACKAGE_ALREADY_INSTALLED,"The package %s is already installed", pkg.name)
+                 self.Finished(EXIT_FAILED)
+                 return
++        if txmbrs:
+             try:
+-                txmbr = self.yumbase.install(name=pkg.name)
+                 successful = self._runYumTransaction()
+                 if not successful:
+                     # _runYumTransaction unlocked yum, set the error code, and called Finished.
+@@ -844,7 +853,7 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+                 return
+         else:
+             self._unlock_yum()
+-            self.ErrorCode(ERROR_PACKAGE_NOT_FOUND,"Package was not found")
++            self.ErrorCode(ERROR_PACKAGE_ALREADY_INSTALLED,"The packages failed to be installed")
+             self.Finished(EXIT_FAILED)
+             return
+@@ -1761,13 +1770,15 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+                                "GPG key not imported, but no GPG information received from Yum.")
+                 self.Finished(EXIT_FAILED)
+                 return False
+-            self.RepoSignatureRequired(keyData['po'].repoid,
+-                                       keyData['keyurl'],
++            id = self._pkg_to_id(keyData['po'])
++            self.RepoSignatureRequired(id,
++                                       keyData['po'].repoid,
++                                       keyData['keyurl'].replace("file://",""),
+                                        keyData['userid'],
+                                        keyData['hexkeyid'],
+                                        keyData['fingerprint'],
+-                                       keyData['timestamp'],
+-                                       SIGTYE_GPG)
++                                       time.ctime(keyData['timestamp']),
++                                       SIGTYPE_GPG)
+             self._unlock_yum()
+             self.ErrorCode(ERROR_GPG_FAILURE,"GPG key not imported.")
+             self.Finished(EXIT_FAILED)
+@@ -1893,6 +1904,10 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+                 type_ = ref['type']
+                 href = ref['href']
+                 title = ref['title'] or ""
++
++                # Description can sometimes have ';' in them, and we use that as the delimiter
++                title = title.replace(";",",")
++
+                 if href:
+                     if type_ in ('bugzilla', 'cve'):
+                         urls[type_].append("%s;%s" % (href, title))
+diff --git a/backends/zypp/pk-backend-zypp.cpp b/backends/zypp/pk-backend-zypp.cpp
+index 15c4b4f..a971707 100644
+--- a/backends/zypp/pk-backend-zypp.cpp
++++ b/backends/zypp/pk-backend-zypp.cpp
+@@ -26,6 +26,7 @@
+ #include <pk-debug.h>
+ #include <string>
+ #include <set>
++#include <glib/gi18n.h>
+ #include <zypp/ZYppFactory.h>
+ #include <zypp/ResObject.h>
+@@ -47,7 +48,6 @@
+ #include <zypp/target/rpm/RpmDb.h>
+ #include <zypp/target/rpm/RpmHeader.h>
+ #include <zypp/target/rpm/RpmException.h>
+-#include <zypp/base/LogControl.h>
+ #include <zypp/TmpPath.h>
+ #include <zypp/sat/Solvable.h>
+@@ -90,12 +90,13 @@ std::map<PkBackend *, std::vector<std::string> *> _signatures;
+ static void
+ backend_initialize (PkBackend *backend)
+ {
+-      zypp::base::LogControl::instance ().logfile("/var/log/pk_backend_zypp");
++      zypp_logging ();
+       pk_debug ("zypp_backend_initialize");
+       EventDirector *eventDirector = new EventDirector (backend);
+       _eventDirectors [backend] = eventDirector;
+       std::vector<std::string> *signature = new std::vector<std::string> ();
+       _signatures [backend] = signature;
++      _updating_self = FALSE;
+ }
+ /**
+@@ -287,7 +288,9 @@ backend_get_filters (PkBackend *backend)
+       return (PkFilterEnum) (PK_FILTER_ENUM_INSTALLED |
+                       PK_FILTER_ENUM_NOT_INSTALLED |
+                       PK_FILTER_ENUM_ARCH |
+-                      PK_FILTER_ENUM_NOT_ARCH);
++                      PK_FILTER_ENUM_NOT_ARCH |
++                      PK_FILTER_ENUM_SOURCE |
++                      PK_FILTER_ENUM_NOT_SOURCE);
+ }
+ static gboolean
+@@ -403,7 +406,7 @@ backend_get_depends_thread (PkBackend *backend)
+                       package_id_temp = pk_package_id_build (it->second.name ().c_str(),
+                                       it->second.edition ().asString ().c_str(),
+                                       it->second.arch ().c_str(),
+-                                      it->second.repository ().name ().c_str());
++                                      it->second.repository ().alias ().c_str());
+                       zypp::PoolItem item = zypp::ResPool::instance ().find (it->second);
+@@ -570,6 +573,32 @@ backend_refresh_cache (PkBackend *backend, gboolean force)
+       pk_backend_thread_create (backend, backend_refresh_cache_thread);
+ }
++/* If a critical self update (see qualifying steps below) is available then only show/install that update first.
++ 1. there is a patch available with the <restart_suggested> tag set
++ 2. The patch contains the package "PackageKit" or "gnome-packagekit
++*/   
++/*static gboolean
++check_for_self_update (PkBackend *backend, std::set<zypp::PoolItem> *candidates)
++{
++      std::set<zypp::PoolItem>::iterator cb = candidates->begin (), ce = candidates->end (), ci;
++      for (ci = cb; ci != ce; ++ci) {
++              zypp::ResObject::constPtr res = ci->resolvable();
++              if (zypp::isKind<zypp::Patch>(res)) {
++                      zypp::Patch::constPtr patch = zypp::asKind<zypp::Patch>(res);
++                      //pk_debug ("restart_suggested is %d",(int)patch->restartSuggested());
++                      if (patch->restartSuggested ()) {
++                              if (!strcmp (PACKAGEKIT_RPM_NAME, res->satSolvable ().name ().c_str ()) ||
++                                              !strcmp (GNOME_PACKAGKEKIT_RPM_NAME, res->satSolvable ().name ().c_str ())) {
++                                      g_free (update_self_patch_name);
++                                      update_self_patch_name = zypp_build_package_id_from_resolvable (res->satSolvable ());
++                                      return TRUE;
++                              }
++                      }
++              }
++      }
++      return FALSE;
++}*/
++
+ static gboolean
+ backend_get_updates_thread (PkBackend *backend)
+ {
+@@ -586,12 +615,23 @@ backend_get_updates_thread (PkBackend *backend)
+       pk_backend_set_percentage (backend, 40);
+       // get all Packages and Patches for Update
+-      std::set<zypp::PoolItem> *candidates = zypp_get_updates ();
+-      std::set<zypp::PoolItem> *candidates2 = zypp_get_patches ();
++      std::set<zypp::PoolItem> *candidates = zypp_get_patches ();
++      std::set<zypp::PoolItem> *candidates2 = new std::set<zypp::PoolItem> ();
++
++      if (!_updating_self) {
++              // exclude the patch-repository
++              std::string patchRepo;
++              if (!candidates->empty ()) {
++                      patchRepo = candidates->begin ()->resolvable ()->repoInfo ().alias ();
++              }
++              
++              candidates2 = zypp_get_updates (patchRepo);
+-      candidates->insert (candidates2->begin (), candidates2->end ());
++              candidates->insert (candidates2->begin (), candidates2->end ());
++      }
+       pk_backend_set_percentage (backend, 80);
++      
+       std::set<zypp::PoolItem>::iterator cb = candidates->begin (), ce = candidates->end (), ci;
+       for (ci = cb; ci != ce; ++ci) {
+               zypp::ResObject::constPtr res = ci->resolvable();
+@@ -716,7 +756,7 @@ backend_install_files_thread (PkBackend *backend)
+               gboolean found = FALSE;
+               for (std::vector<zypp::sat::Solvable>::iterator it = solvables->begin (); it != solvables->end (); it ++) {
+-                     if (it->repository ().name () == "PK_TMP_DIR") {
++                     if (it->repository ().alias () == "PK_TMP_DIR") {
+                              item = new zypp::PoolItem(*it);
+                              found = TRUE;
+                              break;
+@@ -861,14 +901,28 @@ backend_update_system_thread (PkBackend *backend)
+       zypp::ResPool pool = zypp_build_pool (TRUE);
+       pk_backend_set_percentage (backend, 40);
+-      // get all Packages for Update
+-      std::set<zypp::PoolItem> *candidates =  zypp_get_updates ();
+       //get all Patches for Update
+-      std::set<zypp::PoolItem> *candidates2 = zypp_get_patches ();
++      std::set<zypp::PoolItem> *candidates = zypp_get_patches ();
++      std::set<zypp::PoolItem> *candidates2 = new std::set<zypp::PoolItem> ();
++      
++      if (_updating_self) {
++              pk_backend_require_restart (backend, PK_RESTART_ENUM_SESSION, "Package Management System updated - restart needed");
++              _updating_self = FALSE;
++      }
++      else {
++              //disabling patchrepo
++              std::string patchRepo;
++              if (!candidates->empty ()) {
++                      patchRepo = candidates->begin ()->resolvable ()->repoInfo ().alias ();
++              }
++      
++              //get all Updates
++              candidates2 = zypp_get_updates (patchRepo);
+-      //concatenate these sets
++              //concatenate these sets
+-      candidates->insert (candidates->begin (), candidates->end ());
++              candidates->insert (candidates2->begin (), candidates2->end ());
++      }
+       pk_backend_set_percentage (backend, 80);
+       std::set<zypp::PoolItem>::iterator cb = candidates->begin (), ce = candidates->end (), ci;
+@@ -1332,6 +1386,10 @@ backend_repo_enable (PkBackend *backend, const gchar *rid, gboolean enabled)
+               repo = manager.getRepositoryInfo (rid);
+               repo.setEnabled (enabled);
+               manager.modifyRepository (rid, repo);
++              if (!enabled) {
++                      zypp::Repository repository = zypp::sat::Pool::instance ().reposFind (repo.alias ());
++                      repository.eraseFromPool ();
++              }
+       } catch (const zypp::repo::RepoNotFoundException &ex) {
+               pk_backend_error_code (backend, PK_ERROR_ENUM_REPO_NOT_FOUND, "Couldn't find the specified repository");
+               pk_backend_finished (backend);
+@@ -1463,6 +1521,13 @@ backend_update_packages_thread (PkBackend *backend)
+       gchar **package_ids;
+       package_ids = pk_backend_get_strv (backend, "package_ids");
++      zypp_get_patches (); // make shure _updating_self is set
++
++      if (_updating_self) {
++              pk_debug ("updating self and setting restart");
++              pk_backend_require_restart (backend, PK_RESTART_ENUM_SESSION, "Package Management System updated - restart needed");
++              _updating_self = FALSE;
++      }
+       for (guint i = 0; i < g_strv_length (package_ids); i++) {
+               zypp::sat::Solvable solvable = zypp_get_package_by_id (package_ids[i]);
+               zypp::PoolItem item = zypp::ResPool::instance ().find (solvable);
+diff --git a/backends/zypp/zypp-utils.cpp b/backends/zypp/zypp-utils.cpp
+index 2b848f0..d81d0dd 100644
+--- a/backends/zypp/zypp-utils.cpp
++++ b/backends/zypp/zypp-utils.cpp
+@@ -25,6 +25,8 @@
+ #include <sstream>
+ #include <stdlib.h>
+ #include <glib.h>
++#include <glib/gstdio.h>
++#include <glib/gi18n.h>
+ #include <zypp/ZYpp.h>
+ #include <zypp/ZYppFactory.h>
+ #include <zypp/RepoManager.h>
+@@ -45,6 +47,7 @@
+ #include <zypp/target/rpm/RpmDb.h>
+ #include <zypp/target/rpm/RpmHeader.h>
+ #include <zypp/target/rpm/librpmDb.h>
++#include <zypp/base/LogControl.h>
+ #include <zypp/base/Logger.h>
+@@ -53,6 +56,7 @@
+ #include "zypp-utils.h"
+ gchar * _repoName;
++gboolean _updating_self = FALSE;
+ /**
+  * Collect items, select best edition.  This is used to find the best
+  * available or installed.  The name of the class is a bit misleading though ...
+@@ -98,6 +102,34 @@ get_zypp ()
+       return zypp;
+ }
++/**
++  * Enable and rotate zypp logging
++  */
++gboolean
++zypp_logging ()
++{
++      gchar *file = g_strdup ("/var/log/pk_backend_zypp");
++      gchar *file_old = g_strdup ("/var/log/pk_backend_zypp-1");
++
++      if (g_file_test (file, G_FILE_TEST_EXISTS)) {
++              struct stat buffer;
++              g_stat (file, &buffer);
++              // if the file is bigger than 10 MB rotate
++              if ((guint)buffer.st_size > 10485760) {
++                      if (g_file_test (file_old, G_FILE_TEST_EXISTS))
++                              g_remove (file_old);
++                      g_rename (file, file_old);
++              }
++      }
++
++      zypp::base::LogControl::instance ().logfile(file);
++
++      g_free (file);
++      g_free (file_old);
++
++      return TRUE;
++}
++
+ gboolean
+ zypp_is_changeable_media (const zypp::Url &url)
+ {
+@@ -120,13 +152,13 @@ zypp_build_pool (gboolean include_local)
+       zypp::ZYpp::Ptr zypp = get_zypp ();
+       if (include_local == TRUE) {
+-                //FIXME have to wait for fix in zypp (repeated loading of target)
+-                if (zypp::sat::Pool::instance().reposFind( zypp::sat::Pool::systemRepoName() ).solvablesEmpty ())
+-                {
+-                      // Add local resolvables
+-                      zypp::Target_Ptr target = zypp->target ();
+-                      target->load ();
+-                }
++              //FIXME have to wait for fix in zypp (repeated loading of target)
++              if (zypp::sat::Pool::instance().reposFind( zypp::sat::Pool::systemRepoAlias() ).solvablesEmpty ())
++              {
++                      // Add local resolvables
++                      zypp::Target_Ptr target = zypp->target ();
++                      target->load ();
++              }
+       }
+       // Add resolvables from enabled repos
+@@ -163,16 +195,16 @@ zypp_build_pool (gboolean include_local)
+ zypp::ResPool
+ zypp_build_local_pool ()
+ {
+-        zypp::sat::Pool pool = zypp::sat::Pool::instance ();
++      zypp::sat::Pool pool = zypp::sat::Pool::instance ();
+       zypp::ZYpp::Ptr zypp = get_zypp ();
+       try {
+               for (zypp::detail::RepositoryIterator it = pool.reposBegin (); it != pool.reposEnd (); it++){
+                       if (! it->isSystemRepo ())
+-                              pool.reposErase(it->name ());
++                              pool.reposErase(it->alias ());
+               }
+               
+-              if (zypp::sat::Pool::instance().reposFind( zypp::sat::Pool::systemRepoName() ).solvablesEmpty ())
++              if (zypp::sat::Pool::instance().reposFind( zypp::sat::Pool::systemRepoAlias() ).solvablesEmpty ())
+                 {
+                       // Add local resolvables
+                       zypp::Target_Ptr target = zypp->target ();
+@@ -371,27 +403,49 @@ zypp_build_package_id_from_resolvable (zypp::sat::Solvable resolvable)
+       package_id = pk_package_id_build (resolvable.name ().c_str (),
+                                         resolvable.edition ().asString ().c_str (),
+                                         resolvable.arch ().asString ().c_str (),
+-                                        resolvable.repository (). name().c_str ());
++                                        resolvable.repository (). alias().c_str ());
+       return package_id;
+ }
++zypp::RepoInfo
++zypp_get_Repository (PkBackend *backend, const gchar *alias)
++{
++      zypp::RepoInfo info;
++
++      try {
++              zypp::RepoManager manager;
++              info = manager.getRepositoryInfo (alias);
++      } catch (const zypp::repo::RepoNotFoundException &ex) {
++              pk_backend_error_code (backend, PK_ERROR_ENUM_REPO_NOT_FOUND, ex.asUserString().c_str() );
++              return zypp::RepoInfo ();
++      }
++
++      return info;
++}
++
+ gboolean
+ zypp_signature_required (PkBackend *backend, const zypp::PublicKey &key)
+ {
+       gboolean ok = FALSE;
+       if (std::find (_signatures[backend]->begin (), _signatures[backend]->end (), key.id ()) == _signatures[backend]->end ()) {
++              zypp::RepoInfo info = zypp_get_Repository (backend, _repoName);
++              if (info.type () == zypp::repo::RepoType::NONE) {
++                      pk_backend_error_code (backend, PK_ERROR_ENUM_INTERNAL_ERROR, "Repository unknown");
++                      return FALSE;
++              }
++
+               pk_backend_repo_signature_required (backend,
+                               "dummy;0.0.1;i386;data",
+                               _repoName,
+-                              key.path ().c_str (),
+-                              key.id ().c_str (),
++                              info.baseUrlsBegin ()->asString ().c_str (),
++                              key.name ().c_str (),
+                               key.id ().c_str (),
+                               key.fingerprint ().c_str (),
+                               key.created ().asString ().c_str (),
+                               PK_SIGTYPE_ENUM_GPG);
+-              pk_backend_error_code (backend, PK_ERROR_ENUM_GPG_FAILURE, "Repo signature verification failed");
++              pk_backend_error_code (backend, PK_ERROR_ENUM_GPG_FAILURE, "Signature verification for Repository %s failed", _repoName);
+       }else{
+               ok = TRUE;
+       }
+@@ -405,16 +459,22 @@ zypp_signature_required (PkBackend *backend, const std::string &file, const std:
+         gboolean ok = FALSE;
+       
+       if (std::find (_signatures[backend]->begin (), _signatures[backend]->end (), id) == _signatures[backend]->end ()) {
++              zypp::RepoInfo info = zypp_get_Repository (backend, _repoName);
++              if (info.type () == zypp::repo::RepoType::NONE) {
++                      pk_backend_error_code (backend, PK_ERROR_ENUM_INTERNAL_ERROR, "Repository unknown");
++                      return FALSE;
++              }
++              
+               pk_backend_repo_signature_required (backend,
+                               "dummy;0.0.1;i386;data",
+                               _repoName,
+-                              file.c_str (),
++                              info.baseUrlsBegin ()->asString ().c_str (),
+                               id.c_str (),
+                               id.c_str (),
+                               "UNKNOWN",
+                               "UNKNOWN",
+                               PK_SIGTYPE_ENUM_GPG);
+-              pk_backend_error_code (backend, PK_ERROR_ENUM_GPG_FAILURE, "Repo signature verification failed");
++              pk_backend_error_code (backend, PK_ERROR_ENUM_GPG_FAILURE, "Signature verification for Repository %s failed", _repoName);
+       }else{
+               ok = TRUE;
+       }
+@@ -428,16 +488,22 @@ zypp_signature_required (PkBackend *backend, const std::string &file)
+       gboolean ok = FALSE;
+       if (std::find (_signatures[backend]->begin (), _signatures[backend]->end (), file) == _signatures[backend]->end ()) {
+-              pk_backend_repo_signature_required (backend,
++              zypp::RepoInfo info = zypp_get_Repository (backend, _repoName);
++              if (info.type () == zypp::repo::RepoType::NONE) {
++                      pk_backend_error_code (backend, PK_ERROR_ENUM_INTERNAL_ERROR, "Repository unknown");
++                      return FALSE;
++              }
++              
++              pk_backend_repo_signature_required (backend,
+                               "dummy;0.0.1;i386;data",
+                               _repoName,
+-                              file.c_str (),
++                              info.baseUrlsBegin ()->asString ().c_str (),
+                               "UNKNOWN",
+                               file.c_str (),
+                               "UNKNOWN",
+                               "UNKNOWN",
+                               PK_SIGTYPE_ENUM_GPG);
+-              pk_backend_error_code (backend, PK_ERROR_ENUM_GPG_FAILURE, "Repo signature verification failed");
++              pk_backend_error_code (backend, PK_ERROR_ENUM_GPG_FAILURE, "Signature verification for Repository %s failed", _repoName);
+       }else{
+               ok = TRUE;
+       }
+@@ -481,6 +547,12 @@ zypp_emit_packages_in_list (PkBackend *backend, std::vector<zypp::sat::Solvable>
+                                                       system_and_package_are_x86 (*it))
+                                               print = FALSE;
+                               }
++                              if (i == PK_FILTER_ENUM_SOURCE && !(zypp::isKind<zypp::SrcPackage>(*it))) {
++                                      print = FALSE;
++                              }
++                              if (i == PK_FILTER_ENUM_NOT_SOURCE && zypp::isKind<zypp::SrcPackage>(*it)) {
++                                      print = FALSE;
++                              }
+                               //const gchar * myarch = zypp::ZConfig::defaultSystemArchitecture().asString().c_str();
+                               //pk_debug ("my default arch is %s", myarch);
+                       }
+@@ -527,7 +599,7 @@ zypp_find_arch_update_item (const zypp::ResPool & pool, zypp::PoolItem item)
+ }
+ std::set<zypp::PoolItem> *
+-zypp_get_updates ()
++zypp_get_updates (std::string repo)
+ {
+         std::set<zypp::PoolItem> *pks = new std::set<zypp::PoolItem> ();
+         zypp::ResPool pool = zypp::ResPool::instance ();
+@@ -542,7 +614,12 @@ zypp_get_updates ()
+                 zypp::PoolItem candidate =  zypp_find_arch_update_item (pool, *it);
+                 if (!candidate.resolvable ())
+                         continue;
+-                pks->insert (candidate);
++              if (repo.empty ()) {
++                      pks->insert (candidate);
++              }else{
++                      if (candidate->repoInfo ().alias ().compare (repo) != 0)
++                              pks->insert (candidate);
++              }
+         }
+         return pks;
+@@ -552,6 +629,7 @@ std::set<zypp::PoolItem> *
+ zypp_get_patches ()
+ {
+         std::set<zypp::PoolItem> *patches = new std::set<zypp::PoolItem> ();
++      _updating_self = FALSE;
+         zypp::ZYpp::Ptr zypp;
+         zypp = get_zypp ();
+@@ -561,8 +639,18 @@ zypp_get_patches ()
+         for (zypp::ResPoolProxy::const_iterator it = zypp->poolProxy ().byKindBegin<zypp::Patch>();
+                         it != zypp->poolProxy ().byKindEnd<zypp::Patch>(); it ++) {
+                 // check if patch is needed 
+-                if((*it)->candidateObj ().isBroken())
++                if((*it)->candidateObj ().isBroken()) {
+                         patches->insert ((*it)->candidateObj ());
++                      zypp::Patch::constPtr patch = zypp::asKind<zypp::Patch>((*it)->candidateObj ().resolvable ());
++
++                      // check if the patch updates libzypp or packageKit and show only this one
++                      if (patch->restartSuggested ()) {
++                              _updating_self = TRUE;
++                              patches->clear ();
++                              patches->insert ((*it)->candidateObj ());
++                              break;
++                      }
++              }
+         }
+diff --git a/backends/zypp/zypp-utils.h b/backends/zypp/zypp-utils.h
+index 9e3bad1..4f785cf 100644
+--- a/backends/zypp/zypp-utils.h
++++ b/backends/zypp/zypp-utils.h
+@@ -62,6 +62,11 @@ typedef enum {
+   */
+ extern std::map<PkBackend *, std::vector<std::string> *> _signatures;
++/** Used to show/install only an update to ourself. This way if we find a critical bug
++  * in the way we update packages we will install the fix before any other updates.
++  */
++extern gboolean _updating_self;
++
+ /** A string to store the last refreshed repo
+   * this is needed for gpg-key handling stuff (UGLY HACK)
+   * FIXME
+@@ -70,6 +75,11 @@ extern gchar *_repoName;
+ zypp::ZYpp::Ptr get_zypp ();
++/**
++  * Enable and rotate logging
++  */
++gboolean zypp_logging ();
++
+ gboolean zypp_is_changeable_media (const zypp::Url &url);
+ /**
+@@ -125,6 +135,12 @@ zypp::sat::Solvable zypp_get_package_by_id (const gchar *package_id);
+ gchar * zypp_build_package_id_from_resolvable (zypp::sat::Solvable resolvable);
+ /**
++  * Get the RepoInfo 
++  */
++zypp::RepoInfo
++zypp_get_Repository (PkBackend *backend, const gchar *alias);
++
++/**
+   * Ask the User if it is OK to import an GPG-Key for a repo
+   */
+ gboolean zypp_signature_required (PkBackend *backend, const zypp::PublicKey &key);
+@@ -145,9 +161,9 @@ gboolean zypp_signature_required (PkBackend *backend, const std::string &file, c
+ zypp::PoolItem zypp_find_arch_update_item (const zypp::ResPool & pool, zypp::PoolItem item);
+ /**
+-  * Returns a set of all packages the could be updated
++  * Returns a set of all packages the could be updated (you're able to exclude a repo)
+   */
+-std::set<zypp::PoolItem> * zypp_get_updates ();
++std::set<zypp::PoolItem> * zypp_get_updates (std::string repo);
+ /**
+   * Returns a set of all patches the could be installed
+diff --git a/client/pk-console.c b/client/pk-console.c
+index 5a05a8e..ec93978 100644
+--- a/client/pk-console.c
++++ b/client/pk-console.c
+@@ -76,7 +76,6 @@ pk_console_bar (guint subpercentage)
+               return;
+       }
+       if (!has_output_bar) {
+-              pk_warning ("no bar");
+               return;
+       }
+       /* restore cursor */
+@@ -487,6 +486,7 @@ pk_console_perhaps_resolve (PkClient *client, PkFilterEnum filter, const gchar *
+       guint i;
+       guint length;
+       PkPackageItem *item;
++      PkPackageList *list;
+       /* have we passed a complete package_id? */
+       valid = pk_package_id_check (package);
+@@ -508,7 +508,9 @@ pk_console_perhaps_resolve (PkClient *client, PkFilterEnum filter, const gchar *
+       }
+       /* get length of items found */
+-      length = pk_client_package_buffer_get_size (client_task);
++      list = pk_client_get_package_list (client_task);
++      length = pk_package_list_get_size (list);
++      g_object_unref (list);
+       /* didn't resolve to anything, try to get a provide */
+       if (length == 0) {
+@@ -524,8 +526,9 @@ pk_console_perhaps_resolve (PkClient *client, PkFilterEnum filter, const gchar *
+               }
+       }
+-      /* get length of items found again (we might have has success) */
+-      length = pk_client_package_buffer_get_size (client_task);
++      /* get length of items found again (we might have had success) */
++      list = pk_client_get_package_list (client_task);
++      length = pk_package_list_get_size (list);
+       if (length == 0) {
+               pk_warning (_("Could not find a package match"));
+               return NULL;
+@@ -533,7 +536,7 @@ pk_console_perhaps_resolve (PkClient *client, PkFilterEnum filter, const gchar *
+       /* only found one, great! */
+       if (length == 1) {
+-              item = pk_client_package_buffer_get_item (client_task, 0);
++              item = pk_package_list_get_item (list, 0);
+               return g_strdup (item->package_id);
+       }
+@@ -543,14 +546,16 @@ pk_console_perhaps_resolve (PkClient *client, PkFilterEnum filter, const gchar *
+       }
+       g_print ("%s\n", _("There are multiple package matches"));
+       for (i=0; i<length; i++) {
+-              item = pk_client_package_buffer_get_item (client_task, i);
++              item = pk_package_list_get_item (list, i);
+               g_print ("%i. %s\n", i+1, item->package_id);
+       }
+       /* find out what package the user wants to use */
+       i = pk_console_get_number (_("Please enter the package number: "), length);
+-      item = pk_client_package_buffer_get_item (client_task, i-1);
++      item = pk_package_list_get_item (list, i-1);
+       pk_debug ("package_id = %s", item->package_id);
++      g_object_unref (list);
++
+       return g_strdup (item->package_id);
+ }
+@@ -574,7 +579,8 @@ pk_console_install_stuff (PkClient *client, gchar **packages, GError **error)
+       array_files = g_ptr_array_new ();
+       length = g_strv_length (packages);
+       for (i=2; i<length; i++) {
+-              is_local = g_file_test (packages[i], G_FILE_TEST_EXISTS);
++              /* are we a local file */
++              is_local = g_file_test (packages[i], G_FILE_TEST_EXISTS & G_FILE_TEST_IS_REGULAR);
+               if (is_local) {
+                       g_ptr_array_add (array_files, g_strdup (packages[i]));
+               } else {
+@@ -720,6 +726,7 @@ pk_console_remove_packages (PkClient *client, gchar **packages, GError **error)
+       GPtrArray *array;
+       gchar **package_ids = NULL;
+       PkPackageList *list;
++      PkPackageList *list_single;
+       array = g_ptr_array_new ();
+       list = pk_package_list_new ();
+@@ -769,11 +776,13 @@ pk_console_remove_packages (PkClient *client, gchar **packages, GError **error)
+               }
+               /* see how many packages there are */
+-              size = pk_client_package_buffer_get_size (client_task);
++              list_single = pk_client_get_package_list (client_task);
++              size = pk_package_list_get_size (list_single);
+               for (j=0; j<size; j++) {
+-                      item = pk_client_package_buffer_get_item (client_task, j);
++                      item = pk_package_list_get_item (list_single, j);
+                       pk_package_list_add_item (list, item);
+               }
++              g_object_unref (list_single);
+       }
+       /* one of the get-requires failed */
+diff --git a/client/pk-import-desktop.c b/client/pk-import-desktop.c
+index f5be0a5..bfe364f 100644
+--- a/client/pk-import-desktop.c
++++ b/client/pk-import-desktop.c
+@@ -44,53 +44,58 @@ static gchar *
+ pk_desktop_get_name_for_file (const gchar *filename)
+ {
+       guint size;
+-      gchar *name;
++      gchar *name = NULL;
+       PkPackageItem *item;
+       PkPackageId *pid;
+       gboolean ret;
+       GError *error = NULL;
++      PkPackageList *list = NULL;
+       /* use PK to find the correct package */
+       ret = pk_client_reset (client, &error);
+       if (!ret) {
+               pk_warning ("failed to reset client: %s", error->message);
+               g_error_free (error);
+-              return NULL;
++              goto out;
+       }
+       ret = pk_client_search_file (client, PK_FILTER_ENUM_INSTALLED, filename, &error);
+       if (!ret) {
+               pk_warning ("failed to search file: %s", error->message);
+               g_error_free (error);
+-              return NULL;
++              goto out;
+       }
+       /* check that we only matched one package */
+-      size = pk_client_package_buffer_get_size (client);
++      list = pk_client_get_package_list (client);
++      size = pk_package_list_get_size (list);
+       if (size != 1) {
+               pk_warning ("not correct size, %i", size);
+-              return NULL;
++              goto out;
+       }
+       /* get the item */
+-      item = pk_client_package_buffer_get_item (client, 0);
++      item = pk_package_list_get_item (list, 0);
+       if (item == NULL) {
+               pk_error ("cannot get item");
+-              return NULL;
++              goto out;
+       }
+       /* get the package name */
+       pid = pk_package_id_new_from_string (item->package_id);
+       if (pid == NULL) {
+               pk_error ("cannot allocate package id");
+-              return NULL;
++              goto out;
+       }
+       /* strip the name */
+       name = g_strdup (pid->name);
+       pk_package_id_free (pid);
+-      /* return a copy */
++out:
++      if (list != NULL) {
++              g_object_unref (list);
++      }
+       return name;
+ }
+diff --git a/client/pk-import-specspo.c b/client/pk-import-specspo.c
+index cf14cc2..bffd45b 100644
+--- a/client/pk-import-specspo.c
++++ b/client/pk-import-specspo.c
+@@ -56,6 +56,7 @@ pk_import_specspo_get_summary (const gchar *name)
+       gboolean ret;
+       PkPackageItem *item;
+       GError *error = NULL;
++      PkPackageList *list;
+       ret = pk_client_reset (client, &error);
+       if (!ret) {
+@@ -74,18 +75,21 @@ pk_import_specspo_get_summary (const gchar *name)
+       }
+       /* check that we only matched one package */
+-      size = pk_client_package_buffer_get_size (client);
++      list = pk_client_get_package_list (client);
++      size = pk_package_list_get_size (list);
+       if (size != 1) {
+               pk_warning ("not correct size, %i", size);
+               return NULL;
+       }
+       /* get the item */
+-      item = pk_client_package_buffer_get_item (client, 0);
++      item = pk_package_list_get_item (list, 0);
+       if (item == NULL) {
+               pk_error ("cannot get item");
++              g_object_unref (list);
+               return NULL;
+       }
++      g_object_unref (list);
+       return item->summary;
+ }
+diff --git a/configure.ac b/configure.ac
+index f614d2b..7510b03 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -223,7 +223,6 @@ AC_ARG_ENABLE(gprof, AS_HELP_STRING([--enable-gprof],[compile with gprof support
+ # backends
+ AC_ARG_ENABLE(alpm, AS_HELP_STRING([--enable-alpm],[use the ALPM backend]),enable_alpm=$enableval,enable_alpm=no)
+ AC_ARG_ENABLE(apt, AS_HELP_STRING([--enable-apt],[use the APT backend]),enable_apt=$enableval,enable_apt=no)
+-AC_ARG_ENABLE(apt2, AS_HELP_STRING([--enable-apt2],[use the DBus based APT backend]),enable_apt2=$enableval,enable_apt2=no)
+ AC_ARG_ENABLE(box, AS_HELP_STRING([--enable-box],[use the BOX backend]),enable_box=$enableval,enable_box=no)
+ AC_ARG_ENABLE(conary, AS_HELP_STRING([--enable-conary],[use the CONARY backend]),enable_conary=$enableval,enable_conary=no)
+ AC_ARG_ENABLE(dummy, AS_HELP_STRING([--enable-dummy],[use the dummy backend]),enable_dummy=$enableval,enable_dummy=yes)
+@@ -231,6 +230,7 @@ AC_ARG_ENABLE(opkg, AS_HELP_STRING([--enable-opkg],[use the OPKG backend]),enabl
+ AC_ARG_ENABLE(pisi, AS_HELP_STRING([--enable-pisi],[use the PiSi backend]),enable_pisi=$enableval,enable_pisi=no)
+ AC_ARG_ENABLE(poldek, AS_HELP_STRING([--enable-poldek],[use the poldek backend]),enable_poldek=$enableval,enable_poldek=no)
+ AC_ARG_ENABLE(smart, AS_HELP_STRING([--enable-smart],[use the SMART backend]),enable_smart=$enableval,enable_smart=no)
++AC_ARG_ENABLE(urpmi, AS_HELP_STRING([--enable-urpmi],[use the URPMI backend]),enable_urpmi=$enableval,enable_urpmi=no)
+ AC_ARG_ENABLE(yum, AS_HELP_STRING([--enable-yum],[use the YUM backend]),enable_yum=$enableval,enable_yum=no)
+ AC_ARG_ENABLE(yum2, AS_HELP_STRING([--enable-yum2],[use the YUM DBUS backend]),enable_yum2=$enableval,enable_yum2=no)
+ AC_ARG_ENABLE(zypp, AS_HELP_STRING([--enable-zypp],[use the Zypp backend]),enable_zypp=$enableval,enable_zypp=no)
+@@ -238,7 +238,6 @@ AC_ARG_ENABLE(zypp, AS_HELP_STRING([--enable-zypp],[use the Zypp backend]),enabl
+ # export to Makefile.am's
+ AM_CONDITIONAL(BACKEND_TYPE_ALPM, [test x$enable_alpm = xyes], [using ALPM backend])
+ AM_CONDITIONAL(BACKEND_TYPE_APT, [test x$enable_apt = xyes], [using APT backend])
+-AM_CONDITIONAL(BACKEND_TYPE_APT_DBUS, [test x$enable_apt2 = xyes], [using DBus based APT backend])
+ AM_CONDITIONAL(BACKEND_TYPE_BOX, [test x$enable_box = xyes], [using BOX backend])
+ AM_CONDITIONAL(BACKEND_TYPE_CONARY, [test x$enable_conary = xyes], [using CONARY backend])
+ AM_CONDITIONAL(BACKEND_TYPE_DUMMY, [test x$enable_dummy = xyes], [using dummy backend])
+@@ -246,6 +245,7 @@ AM_CONDITIONAL(BACKEND_TYPE_OPKG, [test x$enable_opkg = xyes], [using OPKG backe
+ AM_CONDITIONAL(BACKEND_TYPE_PISI, [test x$enable_pisi = xyes], [using PiSi backend])
+ AM_CONDITIONAL(BACKEND_TYPE_POLDEK, [test x$enable_poldek = xyes], [using poldek backend])
+ AM_CONDITIONAL(BACKEND_TYPE_SMART, [test x$enable_smart = xyes], [using SMART backend])
++AM_CONDITIONAL(BACKEND_TYPE_URPMI, [test x$enable_urpmi = xyes], [using URPMI backend])
+ AM_CONDITIONAL(BACKEND_TYPE_YUM, [test x$enable_yum = xyes], [using YUM backend])
+ AM_CONDITIONAL(BACKEND_TYPE_YUM2, [test x$enable_yum2 = xyes], [using YUM DBUS backend])
+ AM_CONDITIONAL(BACKEND_TYPE_ZYPP, [test x$enable_zypp = xyes], [using Zypp backend])
+@@ -369,7 +369,7 @@ dnl ---------------------------------------------------------------------------
+ AC_ARG_WITH([default_backend],
+           AS_HELP_STRING([--with-default-backend=<option>],
+                          [Default backend to use
+-                           alpm,apt,apt2,box,conary,dummy,smart,yum,pisi,zypp,opkg (dummy)]))
++                           alpm,apt,box,conary,dummy,smart,urpmi,yum,pisi,zypp,opkg (dummy)]))
+ # default to a sane option for the installed tool
+ if test x$with_default_backend = x; then
+       if test -f /usr/bin/yum ; then
+@@ -388,6 +388,8 @@ if test x$with_default_backend = x; then
+               with_default_backend=pisi
+       elif test -f /usr/bin/poldek ; then
+               with_default_backend=poldek
++      elif test -f /usr/bin/urpmq ; then
++              with_default_backend=urpmi
+       elif test -f /usr/bin/zypper ; then
+               with_default_backend=zypp
+       else
+@@ -398,134 +400,8 @@ fi
+ AC_DEFINE_UNQUOTED(DEFAULT_BACKEND, "$with_default_backend", [default backend prefix])
+ AC_SUBST(DEFAULT_BACKEND, "$with_default_backend")
+-AC_DEFUN([APT_BACKEND],
+-[
+-  if test "$APT_PKG_TYPE" == "" ; then
+-         AC_LANG_PUSH(C++)
+-              _libaptpkg_save_cppflags=$CPPFLAGS
+-         CPPFLAGS="$APT_CFLAGS $CPPFLAGS"
+-         _APT_save_libs=$LIBS
+-         LIBS="$APT_LIBS $LIBS"
+-
+-         AC_MSG_CHECKING([for apt support for $1 packages])
+-              AC_RUN_IFELSE(AC_LANG_PROGRAM([
+-              #include <apt-pkg/configuration.h>
+-              #include <apt-pkg/pkgsystem.h>
+-              #include <apt-pkg/init.h>
+-              #include <stdio.h>
+-         ],[
+-              if (pkgInitConfig(*_config) == false)
+-              {
+-                      fprintf(stderr,"pkginitconfig was false");
+-                      return -1;
+-              }
+-              if (pkgInitSystem(*_config, _system) == false)
+-              {
+-                      fprintf(stderr,"pkginitsystem was false");
+-                      return -1;
+-              }
+-              if (_system->ArchiveSupported("$1"))
+-                      return 0;
+-              else
+-                      return 1;
+-              ]),[
+-                      APT_PKG_TYPE=$1
+-                      AC_MSG_RESULT([yes])
+-                      AC_DEFINE(APT_PKG_$2,1,[apt-pkg support files of type $1])
+-              ],)
+-              AC_LANG_POP(C++)
+-         CPPFLAGS=$_libaptpkg_save_cppflags
+-         LIBS=$_libaptpkg_save_libs
+-         unset _libaptpkg_save_cppflags
+-         unset _libaptpkg_save_libs
+-      fi
+-])
+-
+ if test x$enable_apt = xyes; then
+       PY_CHECK_MOD([apt_pkg],,,AC_MSG_ERROR([Apt backend needs python-apt]))
+-
+-      AC_ARG_WITH([apt_search],
+-          AS_HELP_STRING([--with-apt-search=<option>],
+-                         [Apt search type to use - plain,sqlite (plain)]))
+-
+-      if test x$with_apt_search = x; then
+-              with_apt_search=plain
+-      fi
+-    AC_MSG_NOTICE([using $with_apt_search for apt searching])
+-      AC_DEFINE_UNQUOTED(APT_SEARCH, "$with_apt_search", [apt search type])
+-      AC_SUBST(APT_SEARCH, $with_apt_search)
+-      AM_CONDITIONAL(APT_SEARCH_PLAIN, [test x$with_apt_search = xplain], [using plain apt search])
+-      AM_CONDITIONAL(APT_SEARCH_SQLITE, [test x$with_apt_search = xsqlite], [using sqlite apt search])
+-
+-   AC_ARG_WITH(libapt-pkg-lib,
+-       AC_HELP_STRING([--with-libapt-pkg-lib=DIR],[look for the libapt-pkg library in DIR]),
+-       [_libaptpkg_with_lib=$withval],[_libaptpkg_with_lib=no])
+-      if test "$_libaptpkg_with_lib" == "no" ; then
+-              APT_LIBS="-lapt-pkg"
+-      else
+-              APT_LIBS="-L$withval -lapt-pkg"
+-      fi
+-
+-   AC_ARG_WITH(libapt-pkg-includes,
+-       AC_HELP_STRING([--with-libapt-pkg-includes=DIR],[look for the libapt-pkg includes in DIR]),
+-       [_libaptpkg_with_inc=$withval],[_libaptpkg_with_inc=no])
+-      if test "$_libaptpkg_with_inc" == "no" ; then
+-              APT_CFLAGS="-I/usr/include/apt-pkg"
+-      else
+-              APT_CFLAGS="-I$withval"
+-      fi
+-
+-      AC_CACHE_CHECK([whether libapt-pkg is usable],
+-         [libaptpkg_usable],
+-         [
+-         _libaptpkg_save_cppflags=$CPPFLAGS
+-         CPPFLAGS="$APT_CFLAGS $CPPFLAGS"
+-         _APT_save_libs=$LIBS
+-         LIBS="$APT_LIBS $LIBS"
+-
+-         AC_LANG_PUSH(C++)
+-         AC_LINK_IFELSE(AC_LANG_PROGRAM([
+-              #include <apt-pkg/configuration.h>
+-              #include <apt-pkg/pkgsystem.h>
+-              #include <apt-pkg/init.h>
+-              #include <stdio.h>
+-         ],[
+-              if (pkgInitConfig(*_config) == false)
+-              {
+-                      fprintf(stderr,"pkginitconfig was false");
+-                      return -1;
+-              }
+-              if (pkgInitSystem(*_config, _system) == false)
+-              {
+-                      fprintf(stderr,"pkginitsystem was false");
+-                      return -1;
+-              }
+-              return 0;
+-]),libaptpkg_usable=yes,AC_MSG_ERROR([libapt-pkg not found]))
+-
+-         CPPFLAGS=$_libaptpkg_save_cppflags
+-         LIBS=$_libaptpkg_save_libs
+-         unset _libaptpkg_save_cppflags
+-         unset _libaptpkg_save_libs
+-         ])
+-      AC_LANG_POP(C++)
+-
+-      APT_BACKEND(deb,DEB)
+-      APT_BACKEND(rpm,RPM)
+-      if test "$APT_PKG_TYPE" == "" ; then
+-              AC_MSG_ERROR([Couldn't find support for any type of packages that we know about for Apt!])
+-      fi
+-
+-      AC_SUBST(APT_CFLAGS)
+-      AC_SUBST(APT_LIBS)
+-      AC_SUBST(APT_PKG_TYPE)
+-else
+-      AM_CONDITIONAL(APT_SEARCH_PLAIN, [false])
+-      AM_CONDITIONAL(APT_SEARCH_SQLITE, [false])
+-fi
+-
+-if test x$enable_apt2 = xyes; then
+-      PY_CHECK_MOD([apt_pkg],,,AC_MSG_ERROR([Apt backend needs python-apt]))
+ fi
+ if test x$enable_box = xyes; then
+@@ -535,7 +411,7 @@ if test x$enable_box = xyes; then
+ fi
+ if test x$enable_opkg = xyes; then
+-      PKG_CHECK_MODULES(OPKG, libopkg = 0.1.4)
++      PKG_CHECK_MODULES(OPKG, libopkg = 0.1.5)
+       AC_SUBST(OPKG_CFLAGS)
+       AC_SUBST(OPKG_LIBS)
+ fi
+@@ -555,7 +431,7 @@ if test x$enable_poldek = xyes; then
+ fi
+ if test x$enable_zypp = xyes; then
+-      PKG_CHECK_MODULES(ZYPP, libzypp >= 4.14.0)
++      PKG_CHECK_MODULES(ZYPP, libzypp >= 4.25.0)
+       AC_SUBST(ZYPP_CFLAGS)
+       AC_SUBST(ZYPP_LIBS)
+ fi
+@@ -568,11 +444,6 @@ AC_SUBST(PK_PLUGIN_DIR, "\$(libdir)/packagekit-backend")
+ AC_SUBST(PK_PLUGIN_CFLAGS, "-I\$(top_srcdir)/src -I\$(top_srcdir)/libpackagekit $GLIB_CFLAGS $DBUS_CFLAGS $GMODULE_CFLAGS")
+ AC_SUBST(PK_PLUGIN_LIBS, "$GLIB_LIBS $DBUS_LIBS $GMODULE_LIBS")
+-if test x$with_default_backend = xapt; then
+-      # now we've done the conditionals, rename for searching backend
+-      with_default_backend="apt (with $with_apt_search searching)"
+-fi
+-
+ dnl ---------------------------------------------------------------------------
+ dnl - Makefiles, etc.
+ dnl ---------------------------------------------------------------------------
+@@ -592,8 +463,6 @@ contrib/yum-packagekit/Makefile
+ backends/Makefile
+ backends/alpm/Makefile
+ backends/apt/Makefile
+-backends/apt/helpers/Makefile
+-backends/apt2/Makefile
+ backends/box/Makefile
+ backends/conary/Makefile
+ backends/conary/helpers/Makefile
+@@ -603,6 +472,10 @@ backends/smart/Makefile
+ backends/smart/helpers/Makefile
+ backends/test/Makefile
+ backends/test/helpers/Makefile
++backends/urpmi/Makefile
++backends/urpmi/helpers/Makefile
++backends/urpmi/helpers/perl_packagekit/Makefile
++backends/urpmi/helpers/urpmi_backend/Makefile
+ backends/yum/Makefile
+ backends/yum/helpers/Makefile
+ backends/yum2/Makefile
+@@ -650,7 +523,6 @@ echo "
+         Backends:
+         ALPM backend:              ${enable_alpm}
+         APT backend:               ${enable_apt}
+-        APT DBus backend:          ${enable_apt2}
+         BOX backend:               ${enable_box}
+         CONARY backend:            ${enable_conary}
+         dummy backend:             ${enable_dummy}
+@@ -658,6 +530,7 @@ echo "
+         PiSi backend:              ${enable_pisi}
+         poldek backend:            ${enable_poldek}
+         SMART backend:             ${enable_smart}
++        URPMI backend:             ${enable_urpmi}
+         YUM backend:               ${enable_yum}
+         YUM2 backend:              ${enable_yum2}
+         Zypp backend:              ${enable_zypp}
+diff --git a/contrib/PackageKit.spec.in b/contrib/PackageKit.spec.in
+index 4d4a7e3..61a67d1 100644
+--- a/contrib/PackageKit.spec.in
++++ b/contrib/PackageKit.spec.in
+@@ -10,6 +10,7 @@ Summary:   System daemon that is a DBUS abstraction layer for packages
+ Name:      PackageKit
+ Version:   #VERSION#
+ Release:   0.#BUILD#%{?alphatag}%{?dist}
++Epoch:     1
+ License:   GPLv2+
+ Group:     System Environment/Libraries
+ URL:       http://packagekit.freedesktop.org
+@@ -17,8 +18,8 @@ Source0:   http://people.freedesktop.org/~hughsient/releases/%{name}-%{version}.
+ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+ Requires: dbus >= %{dbus_version}
+-Requires: PackageKit-libs = %{version}-%{release}
+-Requires: yum-packagekit = %{version}-%{release}
++Requires: PackageKit-libs = %{epoch}:%{version}-%{release}
++Requires: yum-packagekit = %{epoch}:%{version}-%{release}
+ Requires: yum >= 3.2.6
+ BuildRequires: glib2-devel >= %{glib2_version}
+@@ -69,7 +70,7 @@ will almost instantly update itself to reflect this.
+ Summary: Libraries for accessing PackageKit
+ Group: Development/Libraries
+ Requires: dbus >= %{dbus_version}
+-Requires: %{name} = %{version}-%{release}
++Requires: %{name} = %{epoch}:%{version}-%{release}
+ %description libs
+ Libraries for accessing PackageKit.
+@@ -78,7 +79,7 @@ Libraries for accessing PackageKit.
+ Summary: Cron job and related utilities for PackageKit
+ Group: System Environment/Base
+ Requires: cronie
+-Requires: %{name} = %{version}-%{release}
++Requires: %{name} = %{epoch}:%{version}-%{release}
+ %description cron
+ Crontab and utilities for running PackageKit as a cron job.
+@@ -86,7 +87,7 @@ Crontab and utilities for running PackageKit as a cron job.
+ %package devel
+ Summary: Libraries and headers for PackageKit
+ Group: Development/Libraries
+-Requires: %{name} = %{version}-%{release}
++Requires: %{name} = %{epoch}:%{version}-%{release}
+ Requires: dbus-devel >= %{dbus_version}
+ Requires: pkgconfig
+ Requires: sqlite-devel
+diff --git a/contrib/gnome-packagekit.spec.in b/contrib/gnome-packagekit.spec.in
+index a97fc3b..ded7799 100644
+--- a/contrib/gnome-packagekit.spec.in
++++ b/contrib/gnome-packagekit.spec.in
+@@ -6,6 +6,7 @@ Summary:   GNOME PackageKit Client
+ Name:      gnome-packagekit
+ Version:   #VERSION#
+ Release:   0.#BUILD#%{?alphatag}%{?dist}
++Epoch:     1
+ License:   GPLv2+
+ Group:     Applications/System
+ URL:       http://www.packagekit.org
+diff --git a/docs/html/pk-authors.html b/docs/html/pk-authors.html
+index 607a7a4..7aa298b 100644
+--- a/docs/html/pk-authors.html
++++ b/docs/html/pk-authors.html
+@@ -262,6 +262,22 @@
+  </td>
+ </tr>
++<tr>
++ <td>
++  <img src="img/author-unknown.png" alt=""/><!-- image should be 120px wide -->
++ </td>
++ <td>
++  <h2>Aurelien Lefebvre</h2>
++  <p>
++   Aurelien works for <a href="http://www.mandriva.org">Mandriva</a>.
++   He works on the urpmi backend of PackageKit.
++  </p>
++  <p>
++   <b>Responsible for: urpmi backend</b>
++  </p>
++ </td>
++</tr>
++
+ </table>
+ <p>Back to the <a href="index.html">main page</a></p>
+diff --git a/docs/html/pk-download.html b/docs/html/pk-download.html
+index 0cdc85c..d276a05 100644
+--- a/docs/html/pk-download.html
++++ b/docs/html/pk-download.html
+@@ -44,7 +44,7 @@ easier to install.
+ <h2>Released Versions</h2>
+ <p>
+ Released versions are found on
+-<a href="http://people.freedesktop.org/~hughsient/releases/">people.freedesktop.org</a>.
++<a href="http://www.packagekit.org/releases/">http://www.packagekit.org/releases/</a>.
+ </p>
+ <table>
+ <tr><td><b>Version</b></td><td>&nbsp;&nbsp;</td><td><b>Date</b></td></tr>
+diff --git a/docs/html/pk-faq.html b/docs/html/pk-faq.html
+index efa8344..3e37cc1 100644
+--- a/docs/html/pk-faq.html
++++ b/docs/html/pk-faq.html
+@@ -22,6 +22,7 @@
+ <h2>Table Of Contents</h2>
+ <ul>
+ <li><a href="#how-complete">How complete are the backends?</a></li>
++<li><a href="#1-click-install">Does PackageKit support 1-Click Install?</a></li>
+ <li><a href="#run-as-root">When run as root, gpk-application and pkcon do not work!</a></li>
+ <li><a href="#session-system">Why is there a session service and and a system service?</a></li>
+ <li><a href="#session-methods">How do I use PackageKit in my application?</a></li>
+@@ -52,7 +53,6 @@
+ <tr>
+ <td width="150px">&nbsp;</td>
+ <td><center>apt</center></td>
+-<td><center>apt2</center></td>
+ <td><center>alpm</center></td>
+ <td><center>box</center></td>
+ <td><center>conary</center></td>
+@@ -60,14 +60,14 @@
+ <td><center>pisi</center></td>
+ <td><center>poldek</center></td>
+ <td><center>smart</center></td>
++<td><center>urpmi</center></td>
+ <td><center>yum</center></td>
+ <td><center>yum2</center></td>
+ <td><center>zypp</center></td>
+ </tr>
+ <tr>
+ <td><b>Resolve</b></td>
+-<td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt -->
+-<td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt2 -->
++<td><img src="img/status-good.png" alt="[yes]"/></td><!-- apt -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- alpm -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- box -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- conary -->
+@@ -75,6 +75,7 @@
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- pisi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- poldek -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- smart -->
++<td><img src="img/status-bad.png" alt="[no]"/></td><!-- urpmi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum2 -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- zypp -->
+@@ -82,7 +83,6 @@
+ <tr>
+ <td><b>RefreshCache</b></td>
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- apt -->
+-<td><img src="img/status-good.png" alt="[yes]"/></td><!-- apt2 -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- alpm -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- box -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- conary -->
+@@ -90,14 +90,14 @@
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- pisi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- poldek -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- smart -->
++<td><img src="img/status-good.png" alt="[yes]"/></td><!-- urpmi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum2 -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- zypp -->
+ </tr>
+ <tr>
+ <td><b>GetUpdates</b></td>
+-<td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt -->
+-<td><img src="img/status-good.png" alt="[yes]"/></td><!-- apt2 -->
++<td><img src="img/status-good.png" alt="[yes]"/></td><!-- apt -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- alpm -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- box -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- conary -->
+@@ -105,14 +105,14 @@
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- pisi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- poldek -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- smart -->
++<td><img src="img/status-good.png" alt="[yes]"/></td><!-- urpmi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum2 -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- zypp -->
+ </tr>
+ <tr>
+ <td><b>UpdateSystem</b></td>
+-<td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt -->
+-<td><img src="img/status-good.png" alt="[yes]"/></td><!-- apt2 -->
++<td><img src="img/status-good.png" alt="[yes]"/></td><!-- apt -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- alpm -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- box -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- conary -->
+@@ -120,6 +120,7 @@
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- pisi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- poldek -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- smart -->
++<td><img src="img/status-bad.png" alt="[no]"/></td><!-- urpmi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum2 -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- zypp -->
+@@ -127,7 +128,6 @@
+ <tr>
+ <td><b>SearchName</b></td>
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- apt -->
+-<td><img src="img/status-good.png" alt="[yes]"/></td><!-- apt2 -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- alpm -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- box -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- conary -->
+@@ -135,6 +135,7 @@
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- pisi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- poldek -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- smart -->
++<td><img src="img/status-good.png" alt="[yes]"/></td><!-- urpmi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum2 -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- zypp -->
+@@ -142,7 +143,6 @@
+ <tr>
+ <td><b>SearchDetails</b></td>
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- apt -->
+-<td><img src="img/status-good.png" alt="[yes]"/></td><!-- apt2 -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- alpm -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- box -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- conary -->
+@@ -150,6 +150,7 @@
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- pisi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- poldek -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- smart -->
++<td><img src="img/status-good.png" alt="[yes]"/></td><!-- urpmi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum2 -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- zypp -->
+@@ -157,7 +158,6 @@
+ <tr>
+ <td><b>SearchFile</b></td>
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt -->
+-<td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt2 -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- alpm -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- box -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- conary -->
+@@ -165,6 +165,7 @@
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- pisi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- poldek -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- smart -->
++<td><img src="img/status-good.png" alt="[yes]"/></td><!-- urpmi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum2 -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- zypp -->
+@@ -172,22 +173,21 @@
+ <tr>
+ <td><b>SearchGroup</b></td>
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt -->
+-<td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt2 -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- alpm -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- box -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- conary -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- opkg -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- pisi -->
+-<td><img src="img/status-bad.png" alt="[no]"/></td><!-- poldek -->
++<td><img src="img/status-good.png" alt="[yes]"/></td><!-- poldek -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- smart -->
++<td><img src="img/status-good.png" alt="[yes]"/></td><!-- urpmi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum2 -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- zypp -->
+ </tr>
+ <tr>
+ <td><b>InstallPackages</b></td>
+-<td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt -->
+-<td><img src="img/status-good.png" alt="[yes]"/></td><!-- apt2 -->
++<td><img src="img/status-good.png" alt="[yes]"/></td><!-- apt -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- alpm -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- box -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- conary -->
+@@ -195,6 +195,7 @@
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- pisi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- poldek -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- smart -->
++<td><img src="img/status-good.png" alt="[yes]"/></td><!-- urpmi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum2 -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- zypp -->
+@@ -202,7 +203,6 @@
+ <tr>
+ <td><b>InstallFiles</b></td>
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt -->
+-<td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt2 -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- alpm -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- box -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- conary -->
+@@ -210,14 +210,14 @@
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- pisi -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- poldek -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- smart -->
++<td><img src="img/status-bad.png" alt="[no]"/></td><!-- urpmi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum2 -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- zypp -->
+ </tr>
+ <tr>
+ <td><b>RemovePackages</b></td>
+-<td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt -->
+-<td><img src="img/status-good.png" alt="[yes]"/></td><!-- apt2 -->
++<td><img src="img/status-good.png" alt="[yes]"/></td><!-- apt -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- alpm -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- box -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- conary -->
+@@ -225,6 +225,7 @@
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- pisi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- poldek -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- smart -->
++<td><img src="img/status-good.png" alt="[yes]"/></td><!-- urpmi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum2 -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- zypp -->
+@@ -232,7 +233,6 @@
+ <tr>
+ <td><b>UpdatePackage</b></td>
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt -->
+-<td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt2 -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- alpm -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- box -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- conary -->
+@@ -240,6 +240,7 @@
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- pisi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- poldek -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- smart -->
++<td><img src="img/status-bad.png" alt="[no]"/></td><!-- urpmi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum2 -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- zypp -->
+@@ -247,7 +248,6 @@
+ <tr>
+ <td><b>GetDepends</b></td>
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt -->
+-<td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt2 -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- alpm -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- box -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- conary -->
+@@ -255,6 +255,7 @@
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- pisi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- poldek -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- smart -->
++<td><img src="img/status-good.png" alt="[yes]"/></td><!-- urpmi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum2 -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- zypp -->
+@@ -262,7 +263,6 @@
+ <tr>
+ <td><b>GetRequires</b></td>
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt -->
+-<td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt2 -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- alpm -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- box -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- conary -->
+@@ -270,6 +270,7 @@
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- pisi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- poldek -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- smart -->
++<td><img src="img/status-good.png" alt="[yes]"/></td><!-- urpmi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum2 -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- zypp -->
+@@ -277,7 +278,6 @@
+ <tr>
+ <td><b>GetDetails</b></td>
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- apt -->
+-<td><img src="img/status-good.png" alt="[yes]"/></td><!-- apt2 -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- alpm -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- box -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- conary -->
+@@ -285,6 +285,7 @@
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- pisi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- poldek -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- smart -->
++<td><img src="img/status-good.png" alt="[yes]"/></td><!-- urpmi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum2 -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- zypp -->
+@@ -292,7 +293,6 @@
+ <tr>
+ <td><b>GetFiles</b></td>
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt -->
+-<td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt2 -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- alpm -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- box -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- conary -->
+@@ -300,6 +300,7 @@
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- pisi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- poldek -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- smart -->
++<td><img src="img/status-good.png" alt="[yes]"/></td><!-- urpmi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum2 -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- zypp -->
+@@ -307,7 +308,6 @@
+ <tr>
+ <td><b>GetUpdateDetail</b></td>
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt -->
+-<td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt2 -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- alpm -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- box -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- conary -->
+@@ -315,6 +315,7 @@
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- pisi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- poldek -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- smart -->
++<td><img src="img/status-good.png" alt="[yes]"/></td><!-- urpmi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum2 -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- zypp -->
+@@ -322,7 +323,6 @@
+ <tr>
+ <td><b>GetRepoList</b></td>
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt -->
+-<td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt2 -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- alpm -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- box -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- conary -->
+@@ -330,6 +330,7 @@
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- pisi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- poldek -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- smart -->
++<td><img src="img/status-bad.png" alt="[no]"/></td><!-- urpmi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum2 -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- zypp -->
+@@ -337,7 +338,6 @@
+ <tr>
+ <td><b>RepoEnable</b></td>
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt -->
+-<td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt2 -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- alpm -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- box -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- conary -->
+@@ -345,6 +345,7 @@
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- pisi -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- poldek -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- smart -->
++<td><img src="img/status-bad.png" alt="[no]"/></td><!-- urpmi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum2 -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- zypp -->
+@@ -352,7 +353,6 @@
+ <tr>
+ <td><b>RepoSetData</b></td>
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt -->
+-<td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt2 -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- alpm -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- box -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- conary -->
+@@ -360,6 +360,7 @@
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- pisi -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- poldek -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- smart -->
++<td><img src="img/status-bad.png" alt="[no]"/></td><!-- urpmi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum2 -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- zypp -->
+@@ -367,7 +368,6 @@
+ <tr>
+ <td><b>Cancel</b></td>
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt -->
+-<td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt2 -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- alpm -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- box -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- conary -->
+@@ -375,6 +375,7 @@
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- pisi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- poldek -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- smart -->
++<td><img src="img/status-bad.png" alt="[no]"/></td><!-- urpmi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum2 -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- zypp -->
+@@ -382,7 +383,6 @@
+ <tr>
+ <td><b>ServicePack</b></td>
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt -->
+-<td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt2 -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- alpm -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- box -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- conary -->
+@@ -390,6 +390,7 @@
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- pisi -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- poldek -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- smart -->
++<td><img src="img/status-bad.png" alt="[no]"/></td><!-- urpmi -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- yum -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- yum2 -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- zypp -->
+@@ -397,22 +398,21 @@
+ <tr>
+ <td><b>WhatProvides</b></td>
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt -->
+-<td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt2 -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- alpm -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- box -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- conary -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- opkg -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- pisi -->
+-<td><img src="img/status-bad.png" alt="[no]"/></td><!-- poldek -->
++<td><img src="img/status-good.png" alt="[yes]"/></td><!-- poldek -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- smart -->
++<td><img src="img/status-bad.png" alt="[no]"/></td><!-- urpmi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- yum2 -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- zypp -->
+ </tr>
+ <tr>
+ <td><b>GetPackages</b></td>
+-<td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt -->
+-<td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt2 -->
++<td><img src="img/status-good.png" alt="[yes]"/></td><!-- apt -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- alpm -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- box -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- conary -->
+@@ -420,6 +420,7 @@
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- pisi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- poldek -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- smart -->
++<td><img src="img/status-good.png" alt="[yes]"/></td><!-- urpmi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- yum2 -->
+ <td><img src="img/status-good.png" alt="[good]"/></td><!-- zypp -->
+@@ -431,7 +432,6 @@
+ <tr>
+ <td width="150px">&nbsp;</td>
+ <td><center>apt</center></td>
+-<td><center>apt2</center></td>
+ <td><center>alpm</center></td>
+ <td><center>box</center></td>
+ <td><center>conary</center></td>
+@@ -439,6 +439,7 @@
+ <td><center>pisi</center></td>
+ <td><center>poldek</center></td>
+ <td><center>smart</center></td>
++<td><center>urpmi</center></td>
+ <td><center>yum</center></td>
+ <td><center>yum2</center></td>
+ <td><center>zypp</center></td>
+@@ -446,7 +447,6 @@
+ <tr>
+ <td><b>Installed</b></td>
+ <td><img src="img/status-good.png" alt="[no]"/></td><!-- apt -->
+-<td><img src="img/status-good.png" alt="[no]"/></td><!-- apt2 -->
+ <td><img src="img/status-good.png" alt="[no]"/></td><!-- alpm -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- box -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- conary -->
+@@ -454,6 +454,7 @@
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- pisi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- poldek -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- smart -->
++<td><img src="img/status-good.png" alt="[yes]"/></td><!-- urpmi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum2 -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- zypp -->
+@@ -461,7 +462,6 @@
+ <tr>
+ <td><b>Development</b></td>
+ <td><img src="img/status-good.png" alt="[no]"/></td><!-- apt -->
+-<td><img src="img/status-good.png" alt="[no]"/></td><!-- apt2 -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- alpm -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- box -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- conary -->
+@@ -469,6 +469,7 @@
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- pisi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- poldek -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- smart -->
++<td><img src="img/status-good.png" alt="[yes]"/></td><!-- urpmi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum2 -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- zypp -->
+@@ -476,7 +477,6 @@
+ <tr>
+ <td><b>GUI</b></td>
+ <td><img src="img/status-good.png" alt="[no]"/></td><!-- apt -->
+-<td><img src="img/status-good.png" alt="[no]"/></td><!-- apt2 -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- alpm -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- box -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- conary -->
+@@ -484,6 +484,7 @@
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- pisi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- poldek -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- smart -->
++<td><img src="img/status-good.png" alt="[yes]"/></td><!-- urpmi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum2 -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- zypp -->
+@@ -491,7 +492,6 @@
+ <tr>
+ <td><b>Free</b></td>
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt -->
+-<td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt2 -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- alpm -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- box -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- conary -->
+@@ -499,6 +499,7 @@
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- pisi -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- poldek -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- smart -->
++<td><img src="img/status-bad.png" alt="[no]"/></td><!-- urpmi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- yum -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- yum2 -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- zypp -->
+@@ -506,13 +507,13 @@
+ <tr>
+ <td><b>Visible</b></td>
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt -->
+-<td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt2 -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- alpm -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- box -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- conary -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- opkg -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- pisi -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- poldek -->
++<td><img src="img/status-bad.png" alt="[no]"/></td><!-- urpmi -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- smart -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- yum -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- yum2 -->
+@@ -521,13 +522,13 @@
+ <tr>
+ <td><b>Supported</b></td>
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt -->
+-<td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt2 -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- alpm -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- box -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- conary -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- opkg -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- pisi -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- poldek -->
++<td><img src="img/status-bad.png" alt="[no]"/></td><!-- urpmi -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- smart -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- yum -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- yum2 -->
+@@ -536,13 +537,13 @@
+ <tr>
+ <td><b>Newest</b></td>
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt -->
+-<td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt2 -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- alpm -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- box -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- conary -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- opkg -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- pisi -->
+ <td><img src="img/status-good.png" alt="[yes]"/></td><!-- poldek -->
++<td><img src="img/status-bad.png" alt="[no]"/></td><!-- urpmi -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- smart -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- yum -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- yum2 -->
+@@ -551,13 +552,13 @@
+ <tr>
+ <td><b>Arch</b></td>
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt -->
+-<td><img src="img/status-bad.png" alt="[no]"/></td><!-- apt2 -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- alpm -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- box -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- conary -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- opkg -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- pisi -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- poldek -->
++<td><img src="img/status-bad.png" alt="[no]"/></td><!-- urpmi -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- smart -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- yum -->
+ <td><img src="img/status-bad.png" alt="[no]"/></td><!-- yum2 -->
+@@ -566,6 +567,43 @@
+ </table>
+ <hr>
++<h3><a name="1-click-install">Does PackageKit support 1-Click Install?</a></h3>
++<p>
++No, as they are a potential security problem. The issues are as follows:
++</p>
++<ul>
++<li>
++That some developer creates a repository with a package with a higher package epoch, and then the
++distro releases a critical security package (with an updated version, but smaller epoch) and the
++package does not get upgraded, leaving the user vulnerable.
++</li>
++<li>
++The user installs some random repository, where the developer pushes a few svn packages.
++The developer gets bored, and stop produces updates, and then one of the old packages blocks
++on the distribution update, causing no further automatic system updates.
++</li>
++<li>
++There's no signing of 1-click-install files, so we can't actually be sure that they come from a
++reputable source.
++</li>
++<li>
++There's no localisation in the 1-click-files.
++For instance, if we only show a French language speaker a description of "remote exploit trojan"
++they are not going to understand the description.
++</li>
++</ul>
++<p>
++So what's the solution? Using a standard <code>$vendor-release.rpm</code> or <code>.deb</code>
++you can ship the standard repo or source with a signed GPG key.
++</p>
++<p>
++Quoting Sebastian Heinlein,
++<i>Allowing to easily add third party repositories and install third party software without a
++certification infrastructure is like opening the gates to hell.
++Most user just don't have got the technical understanding to handle this well.</i>
++</p>
++
++<hr>
+ <h3><a name="run-as-root">When run as root, <code>gpk-application</code> and <code>pkcon</code> do not work!</a></h3>
+ <p>
+ GTK+ tools should not be run as the root user, <b>PERIOD</b>.
+diff --git a/docs/spec/pk-concepts.xml b/docs/spec/pk-concepts.xml
+index 0b75b10..51a165a 100644
+--- a/docs/spec/pk-concepts.xml
++++ b/docs/spec/pk-concepts.xml
+@@ -402,6 +402,13 @@
+             signature is not valid in some way.
+             </entry>
+           </row>
++          <row>
++            <entry><literal>package-corrupt</literal></entry>
++            <entry>
++            The downloaded package is corrupt.
++            </entry>
++          </row>
++
+         </tbody>
+       </tgroup>
+     </informaltable>
+diff --git a/docs/spec/pk-signals.xml b/docs/spec/pk-signals.xml
+index a79e647..2970dda 100644
+--- a/docs/spec/pk-signals.xml
++++ b/docs/spec/pk-signals.xml
+@@ -360,11 +360,21 @@
+           </row>
+           <row>
+             <entry><literal>updates</literal></entry>
+-            <entry>A list of package_id's that are to be updated</entry>
++            <entry>
++              A list of package_id's that are to be updated, seporated by <literal>^</literal>.
++              This odd delimited was chosen as <literal>\t</literal> is already being used in the
++              spawned backends, and <literal>^</literal> is a banned character in a package_id.
++              This will change in 0.3.x where <literal>updates</literal> will be a proper string
++              array field.
++            </entry>
+           </row>
+           <row>
+             <entry><literal>obsoletes</literal></entry>
+-            <entry>A list of package_id's that are to be obsoletes</entry>
++            <entry>
++              A list of package_id's that are to be obsoleted, seporated by <literal>^</literal>
++              This will change in 0.3.x where <literal>obsoletes</literal> will be a proper string
++              array field.
++            </entry>
+           </row>
+           <row>
+             <entry><literal>vendor_url</literal></entry>
+diff --git a/etc/PackageKit.conf.in b/etc/PackageKit.conf.in
+index 8f9bd57..7a48320 100644
+--- a/etc/PackageKit.conf.in
++++ b/etc/PackageKit.conf.in
+@@ -39,5 +39,5 @@ DefaultBackend=@defaultbackend@
+ # They are in the format username:password@server:port
+ #
+ # ProxyHTTP=username:password@server.lan:8080
+-# ProxyFTP=username:password@server.lan:21
++# ProxyFTP=server.lan:21
+diff --git a/libpackagekit/pk-client.c b/libpackagekit/pk-client.c
+index dd2387b..8fb82f1 100644
+--- a/libpackagekit/pk-client.c
++++ b/libpackagekit/pk-client.c
+@@ -275,7 +275,7 @@ pk_client_get_tid (PkClient *client)
+  * If the package buffer is enabled then after the transaction has completed
+  * then the package list can be retrieved in one go, rather than processing
+  * each package request async.
+- * If this is not set true explicitly, then pk_client_package_buffer_get_size
++ * If this is not set true explicitly, then pk_client_get_package_list
+  * will always return zero items.
+  *
+  * This is not forced on as there may be significant overhead if the list
+@@ -364,26 +364,7 @@ pk_client_get_require_restart (PkClient *client)
+ }
+ /**
+- * pk_client_package_buffer_get_size:
+- * @client: a valid #PkClient instance
+- *
+- * We do not provide access to the internal package list (as it could be being
+- * updated) so provide a way to get access to the current size here.
+- *
+- * Return value: The size of the package buffer.
+- **/
+-guint
+-pk_client_package_buffer_get_size (PkClient *client)
+-{
+-      g_return_val_if_fail (PK_IS_CLIENT (client), 0);
+-      if (!client->priv->use_buffer) {
+-              return 0;
+-      }
+-      return pk_package_list_get_size (client->priv->package_list);
+-}
+-
+-/**
+- * pk_client_package_buffer_get_item:
++ * pk_client_get_package_list:
+  * @client: a valid #PkClient instance
+  * @item: the item in the package buffer
+  *
+@@ -392,14 +373,17 @@ pk_client_package_buffer_get_size (PkClient *client)
+  *
+  * Return value: The #PkPackageItem or %NULL if not found or invalid
+  **/
+-PkPackageItem *
+-pk_client_package_buffer_get_item (PkClient *client, guint item)
++PkPackageList *
++pk_client_get_package_list (PkClient *client)
+ {
++      PkPackageList *list;
+       g_return_val_if_fail (PK_IS_CLIENT (client), NULL);
+       if (!client->priv->use_buffer) {
+               return NULL;
+       }
+-      return pk_package_list_get_item (client->priv->package_list, item);
++      list = client->priv->package_list;
++      g_object_ref (list);
++      return list;
+ }
+ /**
+@@ -412,6 +396,10 @@ pk_client_finished_cb (DBusGProxy *proxy, const gchar *exit_text, guint runtime,
+       g_return_if_fail (PK_IS_CLIENT (client));
++      /* ref in case we unref the PkClient in ::finished --
++       * see https://bugzilla.novell.com/show_bug.cgi?id=390929 for rationale */
++      g_object_ref (client);
++
+       exit = pk_exit_enum_from_text (exit_text);
+       pk_debug ("emit finished %s, %i", exit_text, runtime);
+@@ -420,16 +408,13 @@ pk_client_finished_cb (DBusGProxy *proxy, const gchar *exit_text, guint runtime,
+       g_signal_emit (client, signals [PK_CLIENT_FINISHED], 0, exit, runtime);
+-      /* check we are still valid */
+-      if (!PK_IS_CLIENT (client)) {
+-              pk_debug ("client was g_object_unref'd in finalise, object no longer valid");
+-              return;
+-      }
+-
+       /* exit our private loop */
+       if (client->priv->synchronous) {
+               g_main_loop_quit (client->priv->loop);
+       }
++
++      /* unref what we previously ref'd */
++      g_object_unref (client);
+ }
+ /**
+@@ -491,7 +476,6 @@ pk_client_package_cb (DBusGProxy   *proxy,
+       /* cache */
+       if (client->priv->use_buffer || client->priv->synchronous) {
+-              pk_debug ("adding to cache array package %i, %s, %s", info, package_id, summary);
+               pk_package_list_add (client->priv->package_list, info, package_id, summary);
+       }
+ }
+@@ -566,16 +550,12 @@ pk_client_details_cb (DBusGProxy  *proxy,
+  * pk_client_files_cb:
+  */
+ static void
+-pk_client_files_cb (DBusGProxy  *proxy,
+-                  const gchar *package_id,
+-                  const gchar *filelist,
+-                  PkClient    *client)
++pk_client_files_cb (DBusGProxy  *proxy, const gchar *package_id, const gchar *filelist, PkClient *client)
+ {
+       g_return_if_fail (PK_IS_CLIENT (client));
+-      pk_debug ("emit files %s, %s", package_id, filelist);
+-      g_signal_emit (client , signals [PK_CLIENT_FILES], 0, package_id,
+-                     filelist);
++      pk_debug ("emit files %s, <lots of files>", package_id);
++      g_signal_emit (client , signals [PK_CLIENT_FILES], 0, package_id, filelist);
+ }
+ /**
+@@ -934,10 +914,8 @@ pk_client_cancel (PkClient *client, GError **error)
+               return TRUE;
+       }
+-      /* special case - if the tid is already finished, then cancel should
+-       * return TRUE as it's what we wanted */
+-      if (pk_strequal (error_local->message, "cancelling a non-running transaction") ||
+-          g_str_has_suffix (error_local->message, " doesn't exist\n")) {
++      /* special case - if the tid is already finished, then cancel should return TRUE */
++      if (g_str_has_suffix (error_local->message, " doesn't exist\n")) {
+               pk_debug ("error ignored '%s' as we are trying to cancel", error_local->message);
+               g_error_free (error_local);
+               return TRUE;
+@@ -1022,7 +1000,7 @@ pk_client_get_updates (PkClient *client, PkFilterEnum filters, GError **error)
+                                G_TYPE_STRING, filter_text,
+                                G_TYPE_INVALID, G_TYPE_INVALID);
+       g_free (filter_text);
+-      if (ret) {
++      if (ret && !client->priv->is_finished) {
+               /* allow clients to respond in the status changed callback */
+               pk_client_change_status (client, PK_STATUS_ENUM_WAIT);
+@@ -1112,7 +1090,7 @@ pk_client_update_system (PkClient *client, GError **error)
+               g_propagate_error (error, error_pk);
+       }
+-      if (ret) {
++      if (ret && !client->priv->is_finished) {
+               /* allow clients to respond in the status changed callback */
+               pk_client_change_status (client, PK_STATUS_ENUM_WAIT);
+@@ -1167,7 +1145,7 @@ pk_client_search_name (PkClient *client, PkFilterEnum filters, const gchar *sear
+                                G_TYPE_STRING, search,
+                                G_TYPE_INVALID, G_TYPE_INVALID);
+       g_free (filter_text);
+-      if (ret) {
++      if (ret && !client->priv->is_finished) {
+               /* allow clients to respond in the status changed callback */
+               pk_client_change_status (client, PK_STATUS_ENUM_WAIT);
+@@ -1223,7 +1201,7 @@ pk_client_search_details (PkClient *client, PkFilterEnum filters, const gchar *s
+                                G_TYPE_STRING, search,
+                                G_TYPE_INVALID, G_TYPE_INVALID);
+       g_free (filter_text);
+-      if (ret) {
++      if (ret && !client->priv->is_finished) {
+               /* allow clients to respond in the status changed callback */
+               pk_client_change_status (client, PK_STATUS_ENUM_WAIT);
+@@ -1277,7 +1255,7 @@ pk_client_search_group (PkClient *client, PkFilterEnum filters, const gchar *sea
+                                G_TYPE_STRING, search,
+                                G_TYPE_INVALID, G_TYPE_INVALID);
+       g_free (filter_text);
+-      if (ret) {
++      if (ret && !client->priv->is_finished) {
+               /* allow clients to respond in the status changed callback */
+               pk_client_change_status (client, PK_STATUS_ENUM_WAIT);
+@@ -1331,7 +1309,7 @@ pk_client_search_file (PkClient *client, PkFilterEnum filters, const gchar *sear
+                                G_TYPE_STRING, search,
+                                G_TYPE_INVALID, G_TYPE_INVALID);
+       g_free (filter_text);
+-      if (ret) {
++      if (ret && !client->priv->is_finished) {
+               /* allow clients to respond in the status changed callback */
+               pk_client_change_status (client, PK_STATUS_ENUM_WAIT);
+@@ -1397,7 +1375,7 @@ pk_client_get_depends (PkClient *client, PkFilterEnum filters, const gchar *pack
+                                G_TYPE_BOOLEAN, recursive,
+                                G_TYPE_INVALID, G_TYPE_INVALID);
+       g_free (filter_text);
+-      if (ret) {
++      if (ret && !client->priv->is_finished) {
+               /* allow clients to respond in the status changed callback */
+               pk_client_change_status (client, PK_STATUS_ENUM_WAIT);
+@@ -1448,7 +1426,7 @@ pk_client_get_packages (PkClient *client, PkFilterEnum filters, GError **error)
+                                G_TYPE_STRING, filter_text,
+                                G_TYPE_INVALID, G_TYPE_INVALID);
+       g_free (filter_text);
+-      if (ret) {
++      if (ret && !client->priv->is_finished) {
+               /* allow clients to respond in the status changed callback */
+               pk_client_change_status (client, PK_STATUS_ENUM_WAIT);
+@@ -1514,7 +1492,7 @@ pk_client_get_requires (PkClient *client, PkFilterEnum filters, const gchar *pac
+                                G_TYPE_BOOLEAN, recursive,
+                                G_TYPE_INVALID, G_TYPE_INVALID);
+       g_free (filter_text);
+-      if (ret) {
++      if (ret && !client->priv->is_finished) {
+               /* allow clients to respond in the status changed callback */
+               pk_client_change_status (client, PK_STATUS_ENUM_WAIT);
+@@ -1579,7 +1557,7 @@ pk_client_what_provides (PkClient *client, PkFilterEnum filters, PkProvidesEnum
+                                G_TYPE_STRING, search,
+                                G_TYPE_INVALID, G_TYPE_INVALID);
+       g_free (filter_text);
+-      if (ret) {
++      if (ret && !client->priv->is_finished) {
+               /* allow clients to respond in the status changed callback */
+               pk_client_change_status (client, PK_STATUS_ENUM_WAIT);
+@@ -1637,7 +1615,7 @@ pk_client_get_update_detail (PkClient *client, const gchar *package_id, GError *
+       ret = dbus_g_proxy_call (client->priv->proxy, "GetUpdateDetail", error,
+                                G_TYPE_STRING, package_id,
+                                G_TYPE_INVALID, G_TYPE_INVALID);
+-      if (ret) {
++      if (ret && !client->priv->is_finished) {
+               /* allow clients to respond in the status changed callback */
+               pk_client_change_status (client, PK_STATUS_ENUM_WAIT);
+@@ -1686,7 +1664,7 @@ pk_client_rollback (PkClient *client, const gchar *transaction_id, GError **erro
+       ret = dbus_g_proxy_call (client->priv->proxy, "Rollback", error,
+                                G_TYPE_STRING, transaction_id,
+                                G_TYPE_INVALID, G_TYPE_INVALID);
+-      if (ret) {
++      if (ret && !client->priv->is_finished) {
+               /* allow clients to respond in the status changed callback */
+               pk_client_change_status (client, PK_STATUS_ENUM_WAIT);
+@@ -1743,7 +1721,7 @@ pk_client_resolve (PkClient *client, PkFilterEnum filters, const gchar *package,
+                                G_TYPE_STRING, package,
+                                G_TYPE_INVALID, G_TYPE_INVALID);
+       g_free (filter_text);
+-      if (ret) {
++      if (ret && !client->priv->is_finished) {
+               /* allow clients to respond in the status changed callback */
+               pk_client_change_status (client, PK_STATUS_ENUM_WAIT);
+@@ -1801,7 +1779,7 @@ pk_client_get_details (PkClient *client, const gchar *package_id, GError **error
+       ret = dbus_g_proxy_call (client->priv->proxy, "GetDetails", error,
+                                G_TYPE_STRING, package_id,
+                                G_TYPE_INVALID, G_TYPE_INVALID);
+-      if (ret) {
++      if (ret && !client->priv->is_finished) {
+               /* allow clients to respond in the status changed callback */
+               pk_client_change_status (client, PK_STATUS_ENUM_WAIT);
+@@ -1858,7 +1836,7 @@ pk_client_get_files (PkClient *client, const gchar *package_id, GError **error)
+       ret = dbus_g_proxy_call (client->priv->proxy, "GetFiles", error,
+                                G_TYPE_STRING, package_id,
+                                G_TYPE_INVALID, G_TYPE_INVALID);
+-      if (ret) {
++      if (ret && !client->priv->is_finished) {
+               /* allow clients to respond in the status changed callback */
+               pk_client_change_status (client, PK_STATUS_ENUM_WAIT);
+@@ -1963,7 +1941,7 @@ pk_client_remove_packages (PkClient *client, gchar **package_ids, gboolean allow
+               g_propagate_error (error, error_pk);
+       }
+-      if (ret) {
++      if (ret && !client->priv->is_finished) {
+               /* allow clients to respond in the status changed callback */
+               pk_client_change_status (client, PK_STATUS_ENUM_WAIT);
+@@ -2048,7 +2026,7 @@ pk_client_refresh_cache (PkClient *client, gboolean force, GError **error)
+               g_propagate_error (error, error_pk);
+       }
+-      if (ret) {
++      if (ret && !client->priv->is_finished) {
+               /* allow clients to respond in the status changed callback */
+               pk_client_change_status (client, PK_STATUS_ENUM_WAIT);
+@@ -2142,7 +2120,7 @@ pk_client_install_packages (PkClient *client, gchar **package_ids, GError **erro
+               g_propagate_error (error, error_pk);
+       }
+-      if (ret) {
++      if (ret && !client->priv->is_finished) {
+               /* allow clients to respond in the status changed callback */
+               pk_client_change_status (client, PK_STATUS_ENUM_WAIT);
+@@ -2242,7 +2220,7 @@ pk_client_install_signature (PkClient *client, PkSigTypeEnum type, const gchar *
+               g_propagate_error (error, error_pk);
+       }
+-      if (ret) {
++      if (ret && !client->priv->is_finished) {
+               /* allow clients to respond in the status changed callback */
+               pk_client_change_status (client, PK_STATUS_ENUM_WAIT);
+@@ -2340,7 +2318,7 @@ pk_client_update_packages (PkClient *client, gchar **package_ids, GError **error
+               g_propagate_error (error, error_pk);
+       }
+-      if (ret) {
++      if (ret && !client->priv->is_finished) {
+               /* allow clients to respond in the status changed callback */
+               pk_client_change_status (client, PK_STATUS_ENUM_WAIT);
+@@ -2570,7 +2548,7 @@ pk_client_install_files (PkClient *client, gboolean trusted, gchar **files_rel,
+               g_propagate_error (error, error_pk);
+       }
+-      if (ret) {
++      if (ret && !client->priv->is_finished) {
+               /* allow clients to respond in the status changed callback */
+               pk_client_change_status (client, PK_STATUS_ENUM_WAIT);
+@@ -2622,7 +2600,7 @@ pk_client_get_repo_list (PkClient *client, PkFilterEnum filters, GError **error)
+                                G_TYPE_INVALID, G_TYPE_INVALID);
+       g_free (filter_text);
+       pk_client_error_fixup (error);
+-      if (ret) {
++      if (ret && !client->priv->is_finished) {
+               /* allow clients to respond in the status changed callback */
+               pk_client_change_status (client, PK_STATUS_ENUM_WAIT);
+@@ -2703,7 +2681,7 @@ pk_client_accept_eula (PkClient *client, const gchar *eula_id, GError **error)
+               g_propagate_error (error, error_pk);
+       }
+-      if (ret) {
++      if (ret && !client->priv->is_finished) {
+               /* allow clients to respond in the status changed callback */
+               pk_client_change_status (client, PK_STATUS_ENUM_WAIT);
+@@ -2787,7 +2765,7 @@ pk_client_repo_enable (PkClient *client, const gchar *repo_id, gboolean enabled,
+               g_propagate_error (error, error_pk);
+       }
+-      if (ret) {
++      if (ret && !client->priv->is_finished) {
+               /* allow clients to respond in the status changed callback */
+               pk_client_change_status (client, PK_STATUS_ENUM_WAIT);
+@@ -2880,7 +2858,7 @@ pk_client_repo_set_data (PkClient *client, const gchar *repo_id, const gchar *pa
+               g_propagate_error (error, error_pk);
+       }
+-      if (ret) {
++      if (ret && !client->priv->is_finished) {
+               /* allow clients to respond in the status changed callback */
+               pk_client_change_status (client, PK_STATUS_ENUM_WAIT);
+@@ -2957,7 +2935,7 @@ pk_client_get_old_transactions (PkClient *client, guint number, GError **error)
+                                G_TYPE_UINT, number,
+                                G_TYPE_INVALID, G_TYPE_INVALID);
+       pk_client_error_fixup (error);
+-      if (ret) {
++      if (ret && !client->priv->is_finished) {
+               /* allow clients to respond in the status changed callback */
+               pk_client_change_status (client, PK_STATUS_ENUM_WAIT);
+       }
+@@ -3085,6 +3063,7 @@ pk_client_set_tid (PkClient *client, const gchar *tid, GError **error)
+               return FALSE;
+       }
+       client->priv->tid = g_strdup (tid);
++      pk_debug ("set tid %s on %p", client->priv->tid, client);
+       dbus_g_proxy_add_signal (proxy, "Finished",
+                                G_TYPE_STRING, G_TYPE_UINT, G_TYPE_INVALID);
+@@ -3523,9 +3502,8 @@ pk_client_reset (PkClient *client, GError **error)
+       g_return_val_if_fail (PK_IS_CLIENT (client), FALSE);
+-      if (client->priv->tid != NULL &&
+-          client->priv->is_finished != TRUE) {
+-              pk_debug ("not exit status, will try to cancel");
++      if (client->priv->tid != NULL && !client->priv->is_finished) {
++              pk_debug ("not exit status, will try to cancel tid %s", client->priv->tid);
+               /* we try to cancel the running tranaction */
+               ret = pk_client_cancel (client, error);
+               if (!ret) {
+@@ -3790,6 +3768,7 @@ libst_client (LibSelfTest *test)
+       guint size_new;
+       guint i;
+       gchar *file;
++      PkPackageList *list;
+       if (libst_start (test, "PkClient", CLASS_AUTO) == FALSE) {
+               return;
+@@ -3833,6 +3812,15 @@ libst_client (LibSelfTest *test)
+               libst_failed (test, NULL);
+       }
++      /************************************************************/
++      libst_title (test, "reset client, unused");
++      ret = pk_client_reset (client, NULL);
++      if (ret) {
++              libst_success (test, NULL);
++      } else {
++              libst_failed (test, NULL);
++      }
++
+       /* check use after finalise */
+       g_signal_connect (client, "finished",
+                         G_CALLBACK (libst_client_finished_cb), test);
+@@ -3871,7 +3859,9 @@ libst_client (LibSelfTest *test)
+       }
+       /* get size */
+-      size = pk_client_package_buffer_get_size (client);
++      list = pk_client_get_package_list (client);
++      size = pk_package_list_get_size (list);
++      g_object_unref (list);
+       if (size == 0) {
+               libst_failed (test, "failed: to get any results");
+       }
+@@ -3891,7 +3881,9 @@ libst_client (LibSelfTest *test)
+                       g_error_free (error);
+               }
+               /* check we got the same results */
+-              size_new = pk_client_package_buffer_get_size (client);
++              list = pk_client_get_package_list (client);
++              size_new = pk_package_list_get_size (list);
++              g_object_unref (list);
+               if (size != size_new) {
+                       libst_failed (test, "old size %i, new size %", size, size_new);
+               }
+diff --git a/libpackagekit/pk-client.h b/libpackagekit/pk-client.h
+index 2b1d1a2..6617159 100644
+--- a/libpackagekit/pk-client.h
++++ b/libpackagekit/pk-client.h
+@@ -346,9 +346,7 @@ gboolean    pk_client_repo_set_data                (PkClient       *client,
+                                                        G_GNUC_WARN_UNUSED_RESULT;
+ /* cached stuff */
+-guint          pk_client_package_buffer_get_size      (PkClient       *client);
+-PkPackageItem *pk_client_package_buffer_get_item      (PkClient       *client,
+-                                                       guint           item);
++PkPackageList *pk_client_get_package_list             (PkClient       *client);
+ PkRestartEnum  pk_client_get_require_restart          (PkClient       *client);
+ /* not job specific */
+diff --git a/libpackagekit/pk-common.c b/libpackagekit/pk-common.c
+index 9d3cff7..0be0e6e 100644
+--- a/libpackagekit/pk-common.c
++++ b/libpackagekit/pk-common.c
+@@ -246,7 +246,7 @@ pk_strsafe (const gchar *text)
+       }
+       /* rip out any insane characters */
+-      delimiters = "\\\f\n\r\t\"'";
++      delimiters = "\\\f\r\t\"'";
+       text_safe = g_strdup (text);
+       g_strdelimit (text_safe, delimiters, ' ');
+       return text_safe;
+@@ -613,6 +613,35 @@ pk_strpad_extra (const gchar *data, guint length, guint *extra)
+ }
+ /**
++ * pk_strreplace:
++ * @text: The input text to make safe
++ * @find: What to search for
++ * @replace: What to replace with
++ *
++ * Replaces chars in the text with a replacement.
++ * The %find and %replace variables to not have to be of the same length
++ *
++ * Return value: the new string (copied)
++ **/
++gchar *
++pk_strreplace (const gchar *text, const gchar *find, const gchar *replace)
++{
++      gchar **array;
++      gchar *retval;
++
++      /* common case, not found */
++      if (strstr (text, find) == NULL) {
++              return g_strdup (text);
++      }
++
++      /* split apart and rejoin with new delimiter */
++      array = g_strsplit (text, find, 0);
++      retval = g_strjoinv (replace, array);
++      g_strfreev (array);
++      return retval;
++}
++
++/**
+  * pk_delay_yield:
+  * @delay: the desired delay in seconds
+  *
+@@ -850,6 +879,23 @@ libst_common (LibSelfTest *test)
+       }
+       g_free (text_safe);
++      /************************************************************/
++      libst_title (test, "pk_strequal same argument");
++      temp = "dave";
++      if (pk_strequal (temp, temp)) {
++              libst_success (test, NULL);
++      } else {
++              libst_failed (test, "incorrect ret when both same");
++      }
++
++      /************************************************************/
++      libst_title (test, "pk_strequal both const");
++      if (pk_strequal ("dave", "dave")) {
++              libst_success (test, NULL);
++      } else {
++              libst_failed (test, "incorrect ret when both same");
++      }
++
+       /************************************************************
+        ****************        build var args        **************
+        ************************************************************/
+@@ -1283,6 +1329,48 @@ libst_common (LibSelfTest *test)
+       g_free (text_safe);
+       /************************************************************
++       ****************         Replace          ******************
++       ************************************************************/
++      libst_title (test, "replace start");
++      text_safe = pk_strreplace ("richard\nhughes", "r", "e");
++      if (pk_strequal (text_safe, "eichaed\nhughes")) {
++              libst_success (test, NULL);
++      } else {
++              libst_failed (test, "failed the replace '%s'", text_safe);
++      }
++      g_free (text_safe);
++
++      /************************************************************/
++      libst_title (test, "replace none");
++      text_safe = pk_strreplace ("richard\nhughes", "dave", "e");
++      if (pk_strequal (text_safe, "richard\nhughes")) {
++              libst_success (test, NULL);
++      } else {
++              libst_failed (test, "failed the replace '%s'", text_safe);
++      }
++      g_free (text_safe);
++
++      /************************************************************/
++      libst_title (test, "replace end");
++      text_safe = pk_strreplace ("richard\nhughes", "s", "e");
++      if (pk_strequal (text_safe, "richard\nhughee")) {
++              libst_success (test, NULL);
++      } else {
++              libst_failed (test, "failed the replace '%s'", text_safe);
++      }
++      g_free (text_safe);
++
++      /************************************************************/
++      libst_title (test, "replace unicode");
++      text_safe = pk_strreplace ("richard\n- hughes", "\n- ", "\n• ");
++      if (pk_strequal (text_safe, "richard\n• hughes")) {
++              libst_success (test, NULL);
++      } else {
++              libst_failed (test, "failed the replace '%s'", text_safe);
++      }
++      g_free (text_safe);
++
++      /************************************************************
+        ****************         Padding          ******************
+        ************************************************************/
+       libst_title (test, "pad smaller, no extra");
+diff --git a/libpackagekit/pk-common.h b/libpackagekit/pk-common.h
+index 9908ec2..9e5a05e 100644
+--- a/libpackagekit/pk-common.h
++++ b/libpackagekit/pk-common.h
+@@ -84,6 +84,9 @@ gchar                **pk_strsplit                           (const gchar    *id,
+ gchar         *pk_strbuild_va                         (const gchar    *first_element,
+                                                        va_list        *args)
+                                                        G_GNUC_WARN_UNUSED_RESULT;
++gchar         *pk_strreplace                          (const gchar    *text,
++                                                       const gchar    *find,
++                                                       const gchar    *replace);
+ gchar         **pk_ptr_array_to_argv                  (GPtrArray      *array)
+                                                        G_GNUC_WARN_UNUSED_RESULT;
+ gchar         **pk_va_list_to_argv                    (const gchar    *string_first,
+diff --git a/libpackagekit/pk-control.c b/libpackagekit/pk-control.c
+index f2de5ae..5a54ccc 100644
+--- a/libpackagekit/pk-control.c
++++ b/libpackagekit/pk-control.c
+@@ -198,6 +198,43 @@ out:
+ }
+ /**
++ * pk_control_set_proxy:
++ * @control: a valid #PkControl instance
++ * @proxy_http: a HTTP proxy string such as "username:password@server.lan:8080"
++ * @proxy_ftp: a FTP proxy string such as "server.lan:8080"
++ *
++ * Set a proxy on the PK daemon
++ *
++ * Return value: if we set the proxy successfully
++ **/
++gboolean
++pk_control_set_proxy (PkControl *control, const gchar *proxy_http, const gchar *proxy_ftp)
++{
++      gboolean ret = FALSE;
++      GError *error = NULL;
++
++      g_return_val_if_fail (PK_IS_CONTROL (control), PK_GROUP_ENUM_UNKNOWN);
++
++      /* check to see if we have a valid proxy */
++      if (control->priv->proxy == NULL) {
++              pk_warning ("No proxy for manager");
++              goto out;
++      }
++      ret = dbus_g_proxy_call (control->priv->proxy, "SetProxy", &error,
++                               G_TYPE_STRING, proxy_http,
++                               G_TYPE_STRING, proxy_ftp,
++                               G_TYPE_INVALID,
++                               G_TYPE_INVALID);
++      if (!ret) {
++              /* abort as the DBUS method failed */
++              pk_warning ("SetProxy failed :%s", error->message);
++              g_error_free (error);
++      }
++out:
++      return ret;
++}
++
++/**
+  * pk_control_get_groups:
+  * @control: a valid #PkControl instance
+  *
+diff --git a/libpackagekit/pk-control.h b/libpackagekit/pk-control.h
+index 63b30d3..c1b1be8 100644
+--- a/libpackagekit/pk-control.h
++++ b/libpackagekit/pk-control.h
+@@ -88,6 +88,9 @@ PkControl    *pk_control_new                         (void);
+ gboolean       pk_control_allocate_transaction_id     (PkControl      *control,
+                                                        gchar          **tid,
+                                                        GError         **error);
++gboolean       pk_control_set_proxy                   (PkControl      *control,
++                                                       const gchar    *proxy_http,
++                                                       const gchar    *proxy_ftp);
+ PkRoleEnum     pk_control_get_actions                 (PkControl      *control);
+ PkFilterEnum   pk_control_get_filters                 (PkControl      *control);
+ PkGroupEnum    pk_control_get_groups                  (PkControl      *control);
+diff --git a/libpackagekit/pk-enum.c b/libpackagekit/pk-enum.c
+index 5743dcb..9dccdd0 100644
+--- a/libpackagekit/pk-enum.c
++++ b/libpackagekit/pk-enum.c
+@@ -152,6 +152,7 @@ static PkEnumMatch enum_error[] = {
+       {PK_ERROR_ENUM_REPO_NOT_AVAILABLE,      "repo-not-available"},
+       {PK_ERROR_ENUM_INVALID_PACKAGE_FILE,    "invalid-package-file"},
+       {PK_ERROR_ENUM_PACKAGE_INSTALL_BLOCKED, "package-install-blocked"},
++      {PK_ERROR_ENUM_PACKAGE_CORRUPT,         "package-corrupt"},
+       {0, NULL}
+ };
+@@ -417,6 +418,8 @@ static PkEnumMatch enum_free_licenses[] = {
+       {PK_LICENSE_ENUM_XANO,                  "XANO"},
+       {PK_LICENSE_ENUM_VOSTROM,               "VOSTROM"},
+       {PK_LICENSE_ENUM_XEROX,                 "Xerox License"},
++      {PK_LICENSE_ENUM_RICEBSD,               "RiceBSD"},
++      {PK_LICENSE_ENUM_QHULL,                 "Qhull"},
+       {0, NULL}
+ };
+diff --git a/libpackagekit/pk-enum.h b/libpackagekit/pk-enum.h
+index e616b64..4cc317e 100644
+--- a/libpackagekit/pk-enum.h
++++ b/libpackagekit/pk-enum.h
+@@ -256,6 +256,7 @@ typedef enum {
+       PK_ERROR_ENUM_REPO_NOT_AVAILABLE,
+       PK_ERROR_ENUM_INVALID_PACKAGE_FILE,
+       PK_ERROR_ENUM_PACKAGE_INSTALL_BLOCKED,
++      PK_ERROR_ENUM_PACKAGE_CORRUPT,
+       PK_ERROR_ENUM_UNKNOWN
+ } PkErrorCodeEnum;
+@@ -493,6 +494,8 @@ typedef enum {
+       PK_LICENSE_ENUM_XANO,
+       PK_LICENSE_ENUM_VOSTROM,
+       PK_LICENSE_ENUM_XEROX,
++      PK_LICENSE_ENUM_RICEBSD,
++      PK_LICENSE_ENUM_QHULL,
+       PK_LICENSE_ENUM_UNKNOWN
+ } PkLicenseEnum;
+diff --git a/libpackagekit/pk-extra.c b/libpackagekit/pk-extra.c
+index 7f01a4c..d0f0776 100644
+--- a/libpackagekit/pk-extra.c
++++ b/libpackagekit/pk-extra.c
+@@ -130,7 +130,6 @@ pk_extra_populate_package_cache_callback (void *data, gint argc, gchar **argv, g
+       obj->icon_name = icon_name;
+       obj->exec = exec;
+       g_hash_table_insert (extra->priv->hash_package, (gpointer) package, (gpointer) obj);
+-      pk_debug ("adding %s, %s", package, icon_name);
+ out:
+       return 0;
+ }
+@@ -180,7 +179,6 @@ pk_extra_populate_locale_cache_callback (void *data, gint argc, gchar **argv, gc
+       obj = g_new (PkExtraLocaleObj, 1);
+       obj->summary = summary;
+       g_hash_table_insert (extra->priv->hash_locale, (gpointer) package, (gpointer) obj);
+-      pk_debug ("adding %s, %s", package, summary);
+ out:
+       return 0;
+ }
+diff --git a/libpackagekit/pk-package-item.c b/libpackagekit/pk-package-item.c
+index 87905dc..ff4bd4e 100644
+--- a/libpackagekit/pk-package-item.c
++++ b/libpackagekit/pk-package-item.c
+@@ -56,7 +56,6 @@ pk_package_item_new (PkInfoEnum info, const gchar *package_id, const gchar *summ
+       g_return_val_if_fail (package_id != NULL, FALSE);
+-      pk_debug ("adding to cache item package %s, %s, %s", pk_info_enum_to_text (info), package_id, summary);
+       item = g_new0 (PkPackageItem, 1);
+       item->info = info;
+       item->package_id = g_strdup (package_id);
+diff --git a/libpackagekit/pk-package-list.c b/libpackagekit/pk-package-list.c
+index 5d95e1b..6bdb0d4 100644
+--- a/libpackagekit/pk-package-list.c
++++ b/libpackagekit/pk-package-list.c
+@@ -77,7 +77,6 @@ pk_package_list_add (PkPackageList *plist, PkInfoEnum info, const gchar *package
+       g_return_val_if_fail (PK_IS_PACKAGE_LIST (plist), FALSE);
+       g_return_val_if_fail (package_id != NULL, FALSE);
+-      pk_debug ("adding to cache array package %s, %s, %s", pk_info_enum_to_text (info), package_id, summary);
+       item = pk_package_item_new (info, package_id, summary);
+       g_ptr_array_add (plist->priv->array, item);
+@@ -104,9 +103,6 @@ pk_package_list_add_item (PkPackageList *plist, PkPackageItem *item)
+               return FALSE;
+       }
+-      pk_debug ("adding to cache array package %s, %s, %s",
+-                pk_info_enum_to_text (item->info), item->package_id, item->summary);
+-
+       item_new = pk_package_item_copy (item);
+       g_ptr_array_add (plist->priv->array, item_new);
+@@ -114,6 +110,30 @@ pk_package_list_add_item (PkPackageList *plist, PkPackageItem *item)
+ }
+ /**
++ * pk_package_list_add_list:
++ *
++ * Makes a deep copy of the list
++ **/
++gboolean
++pk_package_list_add_list (PkPackageList *plist, PkPackageList *list)
++{
++      guint i;
++      guint len;
++      PkPackageItem *item;
++
++      g_return_val_if_fail (PK_IS_PACKAGE_LIST (plist), FALSE);
++      g_return_val_if_fail (PK_IS_PACKAGE_LIST (list), FALSE);
++
++      /* add list to plist */
++      len = pk_package_list_get_size (list);
++      for (i=0; i<len; i++) {
++              item = pk_package_list_get_item (list, i);
++              pk_package_list_add_item (plist, item);
++      }
++      return TRUE;
++}
++
++/**
+  * pk_package_list_get_string:
+  **/
+ gchar *
+diff --git a/libpackagekit/pk-package-list.h b/libpackagekit/pk-package-list.h
+index 9734af4..83901ab 100644
+--- a/libpackagekit/pk-package-list.h
++++ b/libpackagekit/pk-package-list.h
+@@ -59,6 +59,8 @@ gboolean      pk_package_list_add                    (PkPackageList          *plist,
+                                                        const gchar            *summary);
+ gboolean       pk_package_list_add_item               (PkPackageList          *plist,
+                                                        PkPackageItem          *item);
++gboolean       pk_package_list_add_list               (PkPackageList          *plist,
++                                                       PkPackageList          *list);
+ gboolean       pk_package_list_contains               (PkPackageList          *plist,
+                                                        const gchar            *package_id);
+ gboolean       pk_package_list_contains_item          (PkPackageList          *plist,
+diff --git a/libpackagekit/pk-polkit-client.c b/libpackagekit/pk-polkit-client.c
+index dceb656..7308a29 100644
+--- a/libpackagekit/pk-polkit-client.c
++++ b/libpackagekit/pk-polkit-client.c
+@@ -54,9 +54,6 @@ static void     pk_polkit_client_finalize            (GObject           *object);
+ #define POLKIT_DBUS_PATH              "/org/gnome/PolicyKit/Manager"
+ #define POLKIT_DBUS_INTERFACE         "org.gnome.PolicyKit.Manager"
+-/* we only support auth on the the transaction interface */
+-#define       PK_ERROR_REFUSED_BY_POLICY      "org.freedesktop.PackageKit.Transaction.RefusedByPolicy"
+-
+ /**
+  * PkPolkitClientPrivate:
+  *
+@@ -175,7 +172,10 @@ pk_polkit_client_error_denied_by_policy (GError *error)
+       /* check for specific error */
+       error_name = dbus_g_error_get_name (error);
+       pk_debug ("ERROR: %s: %s", error_name, error->message);
+-      if (pk_strequal (error_name, PK_ERROR_REFUSED_BY_POLICY)) {
++      if (pk_strequal (error_name, "org.freedesktop.PackageKit.RefusedByPolicy")) {
++              return TRUE;
++      }
++      if (pk_strequal (error_name, "org.freedesktop.PackageKit.Transaction.RefusedByPolicy")) {
+               return TRUE;
+       }
+       return FALSE;
+diff --git a/libpackagekit/pk-task-list.c b/libpackagekit/pk-task-list.c
+index 76ab022..3dc1db0 100644
+--- a/libpackagekit/pk-task-list.c
++++ b/libpackagekit/pk-task-list.c
+@@ -161,7 +161,7 @@ pk_task_list_status_changed_cb (PkClient *client, PkStatusEnum status, PkTaskLis
+       g_return_if_fail (PK_IS_TASK_LIST (tlist));
+       tid = pk_client_get_tid (client);
+-      pk_debug ("tid %s is now %i", tid, status);
++      pk_debug ("tid %s is now %s", tid, pk_status_enum_to_text (status));
+       /* get correct item */
+       item = pk_task_list_find_existing_tid (tlist, tid);
+diff --git a/po/LINGUAS b/po/LINGUAS
+index 6dbee0e..f87e6b3 100644
+--- a/po/LINGUAS
++++ b/po/LINGUAS
+@@ -5,6 +5,7 @@ es
+ fi
+ fr
+ he
++hu
+ it
+ nl
+ no_nb
+diff --git a/po/de.po b/po/de.po
+index 33d30c1..6e8013e 100644
+--- a/po/de.po
++++ b/po/de.po
+@@ -8,8 +8,8 @@ msgid ""
+ msgstr ""
+ "Project-Id-Version: PackageKit\n"
+ "Report-Msgid-Bugs-To: \n"
+-"POT-Creation-Date: 2008-04-23 01:36+0000\n"
+-"PO-Revision-Date: 2008-04-23 19:28+0100\n"
++"POT-Creation-Date: 2008-05-03 01:22+0000\n"
++"PO-Revision-Date: 2008-05-20 21:52+0100\n"
+ "Last-Translator: Fabian Affolter <fab@fedoraproject.org>\n"
+ "Language-Team: German <fedora-trans-de@redhat.com>\n"
+ "MIME-Version: 1.0\n"
+@@ -18,239 +18,239 @@ msgstr ""
+ "Plural-Forms: nplurals=2; plural=(n != 1);\n"
+ "X-Poedit-Language: German\n"
+-#: ../client/pk-console.c:208
++#: ../client/pk-console.c:224
+ msgid "Update detail"
+ msgstr "Aktualisierungsdetails"
+-#: ../client/pk-console.c:400
++#: ../client/pk-console.c:425
+ msgid "A system restart is required"
+ msgstr "Ein Systemneustart ist erforderlich"
+-#: ../client/pk-console.c:402
++#: ../client/pk-console.c:427
+ msgid "A logout and login is required"
+ msgstr "Eine Neuanmeldung ist erforderlich"
+-#: ../client/pk-console.c:404
++#: ../client/pk-console.c:429
+ msgid "An application restart is required"
+ msgstr "Ein Neustart der Anwendung ist erforderlich"
+-#: ../client/pk-console.c:443
++#: ../client/pk-console.c:474
+ #, c-format
+ msgid "Please enter a number from 1 to %i: "
+ msgstr "Bitte eine Zahl zwischen 1 und %i eingeben: "
+-#: ../client/pk-console.c:493
++#: ../client/pk-console.c:524
+ msgid "Could not find a package match"
+ msgstr "Es konnte kein passendes Paket gefunden werden"
+-#: ../client/pk-console.c:507
++#: ../client/pk-console.c:538
+ msgid "There are multiple package matches"
+ msgstr "Es wurden mehrere passende Paket gefunden"
+ #. find out what package the user wants to use
+-#: ../client/pk-console.c:514
++#: ../client/pk-console.c:545
+ msgid "Please enter the package number: "
+ msgstr "Bitte die Paketnummer eingeben: "
+-#: ../client/pk-console.c:530
++#: ../client/pk-console.c:561
+ msgid "Could not find a package with that name to install, or package already installed"
+ msgstr "Es konnten weder installierte noch zu installierende Paket mit diesem Namen gefunden werden"
+-#: ../client/pk-console.c:612
++#: ../client/pk-console.c:643
+ msgid "Could not find a package with that name to remove"
+ msgstr "Es konnte kein Paket mit diesem Namen zum Deinstallieren gefunden werden"
+-#: ../client/pk-console.c:652
++#: ../client/pk-console.c:683
+ msgid "The following packages have to be removed"
+ msgstr "Die folgenden Paket werden entfernt"
+ #. get user input
+-#: ../client/pk-console.c:661
++#: ../client/pk-console.c:692
+ msgid "Okay to remove additional packages?"
+ msgstr "Die folgenden zusätzlichen Pakete entfernen?"
+-#: ../client/pk-console.c:665
++#: ../client/pk-console.c:696
+ msgid "Cancelled!"
+ msgstr "Abgebrochen!"
+-#: ../client/pk-console.c:687
++#: ../client/pk-console.c:718
+ msgid "Could not find a package with that name to update"
+ msgstr "Es konnte kein Paket mit diesem Namen zum Aktualisieren gefunden werden"
+-#: ../client/pk-console.c:705
++#: ../client/pk-console.c:736
+ msgid "Could not find what packages require this package"
+ msgstr "Es konnte nicht rausgefunden werden, welche Pakete dieses Paket benötigen"
+-#: ../client/pk-console.c:723
++#: ../client/pk-console.c:754
+ msgid "Could not get dependencies for this package"
+ msgstr "Die Abhängigkeiten für dieses Paket konnten nicht ermittelt werden"
+-#: ../client/pk-console.c:741
+-msgid "Could not find a description for this package"
+-msgstr "Die Beschreibung für dieses Paket konnten nicht ermittelt werden"
++#: ../client/pk-console.c:772
++msgid "Could not find details for this package"
++msgstr "Die Details für dieses Paket konnten nicht gefunden werden"
+-#: ../client/pk-console.c:759
++#: ../client/pk-console.c:790
+ msgid "Could not find the files for this package"
+ msgstr "Die Dateien für dieses Paket konnten nicht ermittelt werden"
+-#: ../client/pk-console.c:819
++#: ../client/pk-console.c:870
+ msgid "Package description"
+ msgstr "Paketbeschreibung"
+-#: ../client/pk-console.c:842
++#: ../client/pk-console.c:893
+ msgid "Package files"
+ msgstr "Paketinhalt"
+-#: ../client/pk-console.c:850
++#: ../client/pk-console.c:901
+ msgid "No files"
+ msgstr "Keine Dateien"
+ #. get user input
+-#: ../client/pk-console.c:882
++#: ../client/pk-console.c:933
+ msgid "Okay to import key?"
+ msgstr "Soll der Schlüssel importiert werden?"
+-#: ../client/pk-console.c:885
++#: ../client/pk-console.c:936
+ msgid "Did not import key"
+ msgstr "Den Schlüssel nicht importieren"
+ #. get user input
+-#: ../client/pk-console.c:925
++#: ../client/pk-console.c:976
+ msgid "Do you agree?"
+ msgstr "Sind Sie einverstanden?"
+-#: ../client/pk-console.c:928
++#: ../client/pk-console.c:979
+ msgid "Did not agree to licence, task will fail"
+ msgstr "Lizenz wurde abgelehnt, Aufgabe wird fehlschlagen"
+-#: ../client/pk-console.c:957
++#: ../client/pk-console.c:1008
+ msgid "The daemon crashed mid-transaction!"
+ msgstr "Der Dienst ist während der Verarbeitung abgestürzt!"
+ #. header
+-#: ../client/pk-console.c:1010
++#: ../client/pk-console.c:1061
+ msgid "PackageKit Console Interface"
+ msgstr "PackageKit-Konsolenschnittstelle"
+-#: ../client/pk-console.c:1010
++#: ../client/pk-console.c:1061
+ msgid "Subcommands:"
+ msgstr "Unterbefehle:"
+-#: ../client/pk-console.c:1114
+-#: ../client/pk-monitor.c:100
++#: ../client/pk-console.c:1165
++#: ../client/pk-monitor.c:104
+ #: ../src/pk-main.c:189
+ msgid "Show extra debugging information"
+ msgstr "Zusätzliche Debugging-Informationen anzeigen"
+-#: ../client/pk-console.c:1116
+-#: ../client/pk-monitor.c:102
++#: ../client/pk-console.c:1167
++#: ../client/pk-monitor.c:106
+ msgid "Show the program version and exit"
+ msgstr "Die Programmversion anzeigen und beenden"
+-#: ../client/pk-console.c:1118
++#: ../client/pk-console.c:1169
+ msgid "Set the filter, e.g. installed"
+ msgstr "Setzt den Filter, z. B. installiert"
+-#: ../client/pk-console.c:1120
++#: ../client/pk-console.c:1171
+ msgid "Exit without waiting for actions to complete"
+ msgstr "Beenden ohne auf das Ende der Aktionen zu warten"
+-#: ../client/pk-console.c:1143
++#: ../client/pk-console.c:1194
+ msgid "Could not connect to system DBUS."
+ msgstr "Mit System-DBUS konnte nicht verbunden werden."
+-#: ../client/pk-console.c:1231
++#: ../client/pk-console.c:1288
+ msgid "You need to specify a search type"
+ msgstr "Es muss eine Suchart angegeben werden"
+-#: ../client/pk-console.c:1236
+-#: ../client/pk-console.c:1243
+-#: ../client/pk-console.c:1250
+-#: ../client/pk-console.c:1257
+-#: ../client/pk-console.c:1361
+-#: ../client/pk-console.c:1368
+-#: ../client/pk-console.c:1375
+-#: ../client/pk-console.c:1382
++#: ../client/pk-console.c:1293
++#: ../client/pk-console.c:1300
++#: ../client/pk-console.c:1307
++#: ../client/pk-console.c:1314
++#: ../client/pk-console.c:1421
++#: ../client/pk-console.c:1428
++#: ../client/pk-console.c:1435
++#: ../client/pk-console.c:1442
+ msgid "You need to specify a search term"
+ msgstr "Es muss ein Suchausdruck angegeben werden"
+-#: ../client/pk-console.c:1262
++#: ../client/pk-console.c:1319
+ msgid "Invalid search type"
+ msgstr "Ungültige Suchart"
+-#: ../client/pk-console.c:1267
++#: ../client/pk-console.c:1324
+ msgid "You need to specify a package or file to install"
+ msgstr "Es muss ein Paket oder eine Datei zum Installieren angegeben werden"
+-#: ../client/pk-console.c:1280
++#: ../client/pk-console.c:1339
+ msgid "You need to specify a type, key_id and package_id"
+ msgstr "Es muss ein Typ angegeben werden, key_id oder package_id"
+-#: ../client/pk-console.c:1287
++#: ../client/pk-console.c:1346
+ msgid "You need to specify a package to remove"
+ msgstr "Es muss ein Paket zum Entfernen angegeben werden"
+-#: ../client/pk-console.c:1294
++#: ../client/pk-console.c:1353
+ msgid "You need to specify a eula-id"
+ msgstr "Es muss eine eula-id angegeben werden"
+-#: ../client/pk-console.c:1309
++#: ../client/pk-console.c:1369
+ msgid "You need to specify a package name to resolve"
+ msgstr "Es muss ein Paketname zum Auflösen angegeben werden"
+-#: ../client/pk-console.c:1316
+-#: ../client/pk-console.c:1323
++#: ../client/pk-console.c:1376
++#: ../client/pk-console.c:1383
+ msgid "You need to specify a repo name"
+ msgstr "Es muss ein Repository-Name angegeben werden"
+-#: ../client/pk-console.c:1330
++#: ../client/pk-console.c:1390
+ msgid "You need to specify a repo name/parameter and value"
+ msgstr "Es muss ein Repository-Name/Argument und Wert angegeben werden"
+-#: ../client/pk-console.c:1343
++#: ../client/pk-console.c:1403
+ msgid "You need to specify a time term"
+ msgstr "Es muss ein Zeitausdruck angegeben werden"
+-#: ../client/pk-console.c:1348
++#: ../client/pk-console.c:1408
+ msgid "You need to specify a correct role"
+ msgstr "Es muss eine korrekte Rolle angegeben werden"
+-#: ../client/pk-console.c:1353
++#: ../client/pk-console.c:1413
+ msgid "Failed to get last time"
+ msgstr "Die letzte Zeit konnte nicht abgefragt werden"
+-#: ../client/pk-console.c:1389
+-msgid "You need to specify a package to find the description for"
+-msgstr "Es muss ein Paket angegeben werden zu dem die Beschreibung gefunden werden soll"
++#: ../client/pk-console.c:1449
++msgid "You need to specify a package to find the details for"
++msgstr "Es muss ein Paket angegeben werden zu dem die Details gefunden werden sollen"
+-#: ../client/pk-console.c:1396
++#: ../client/pk-console.c:1456
+ msgid "You need to specify a package to find the files for"
+ msgstr "Es muss ein Paket angegeben werden zu dem die Dateien gefunden werden sollen"
+-#: ../client/pk-console.c:1441
++#: ../client/pk-console.c:1503
+ #, c-format
+ msgid "Option '%s' not supported"
+ msgstr "Option '%s' wird nicht unterstützt"
+-#: ../client/pk-console.c:1452
++#: ../client/pk-console.c:1514
+ msgid "Command failed"
+ msgstr "Befehl fehlgeschlagen"
+-#: ../client/pk-console.c:1456
++#: ../client/pk-console.c:1518
+ msgid "You don't have the necessary privileges for this operation"
+ msgstr "Es fehlen die benötigten Rechte für diese Operation"
+-#: ../client/pk-monitor.c:113
++#: ../client/pk-monitor.c:117
+ msgid "PackageKit Monitor"
+ msgstr "PackageKit Monitor"
+-#: ../client/pk-import-desktop.c:283
++#: ../client/pk-import-desktop.c:293
+ #: ../client/pk-import-specspo.c:169
+ #, c-format
+ msgid "Could not open database: %s"
+ msgstr "Datenbank konnte nicht geöffnet werden: %s"
+-#: ../client/pk-import-desktop.c:284
++#: ../client/pk-import-desktop.c:294
+ #: ../client/pk-import-specspo.c:170
+ msgid "You probably need to run this program as the root user"
+ msgstr "Das Programm muss möglicherweise als Benutzer root ausgeführt werden"
+@@ -308,6 +308,12 @@ msgstr "Es konnte nicht zum System-Bus verbunden werden"
+ msgid "Error trying to start: %s\n"
+ msgstr "Fehler beim Versuch zu starten: %s\n"
++#~ msgid "Could not find a description for this package"
++#~ msgstr "Die Beschreibung für dieses Paket konnten nicht ermittelt werden"
++#~ msgid "You need to specify a package to find the description for"
++#~ msgstr ""
++#~ "Es muss ein Paket angegeben werden zu dem die Beschreibung gefunden "
++#~ "werden soll"
+ #~ msgid "Accept EULA"
+ #~ msgstr "EULA akzeptieren"
+ #~ msgid "Authentication is required to accept a EULA"
+diff --git a/po/hu.po b/po/hu.po
+new file mode 100644
+index 0000000..ea732d0
+--- /dev/null
++++ b/po/hu.po
+@@ -0,0 +1,311 @@
++# SOME DESCRIPTIVE TITLE.
++# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
++# This file is distributed under the same license as the PACKAGE package.
++# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
++#
++msgid ""
++msgstr ""
++"Project-Id-Version: packagekit\n"
++"Report-Msgid-Bugs-To: \n"
++"POT-Creation-Date: 2008-05-18 17:43+0000\n"
++"PO-Revision-Date: 2008-05-19 00:08+0100\n"
++"Last-Translator: Sulyok Péter <peti@fedoraproject.org>\n"
++"Language-Team: Hungarian <fedora-trans-hu@redhat.com>\n"
++"MIME-Version: 1.0\n"
++"Content-Type: text/plain; charset=utf-8\n"
++"Content-Transfer-Encoding: 8bit\n"
++"Plural-Forms: nplurals=2; plural=n>1\n"
++"X-Poedit-Language: Hungarian\n"
++"X-Poedit-Country: HUNGARY\n"
++"X-Poedit-SourceCharset: utf-8\n"
++
++#: ../client/pk-console.c:224
++msgid "Update detail"
++msgstr "Frissítés részletező"
++
++#: ../client/pk-console.c:425
++msgid "A system restart is required"
++msgstr "Rendszer-újraindítás szükséges"
++
++#: ../client/pk-console.c:427
++msgid "A logout and login is required"
++msgstr "Kijelentkezés és bejelentkezés szükséges"
++
++#: ../client/pk-console.c:429
++msgid "An application restart is required"
++msgstr "Alkalmazás-újraindítás szükséges"
++
++#: ../client/pk-console.c:474
++#, c-format
++msgid "Please enter a number from 1 to %i: "
++msgstr "Kérem adjon meg egy számot 1-től %i-ig:"
++
++#: ../client/pk-console.c:524
++msgid "Could not find a package match"
++msgstr "Nincs megfelelő csomag"
++
++#: ../client/pk-console.c:538
++msgid "There are multiple package matches"
++msgstr "Több csomag illik"
++
++#. find out what package the user wants to use
++#: ../client/pk-console.c:545
++msgid "Please enter the package number: "
++msgstr "Kérem adja meg a csomagszámot:"
++
++#: ../client/pk-console.c:561
++msgid "Could not find a package with that name to install, or package already installed"
++msgstr "Nem lehetett csomagot találni azzal a névvel telepítésre, vagy márt telepített csomagot"
++
++#: ../client/pk-console.c:643
++msgid "Could not find a package with that name to remove"
++msgstr "Nem lehetett csomagot találni azzal a névvel törlésre"
++
++#: ../client/pk-console.c:683
++msgid "The following packages have to be removed"
++msgstr "A következő csomagokat kell eltávolítani"
++
++#. get user input
++#: ../client/pk-console.c:692
++msgid "Okay to remove additional packages?"
++msgstr "Eltávolíthatók további csomagok?"
++
++#: ../client/pk-console.c:696
++msgid "Cancelled!"
++msgstr "Megszakítva!"
++
++#: ../client/pk-console.c:718
++msgid "Could not find a package with that name to update"
++msgstr "Nem lehetett csomagot találni azzal a névvel frissítésre"
++
++#: ../client/pk-console.c:736
++msgid "Could not find what packages require this package"
++msgstr "Nem lehetett megtudni mely csomagok szükségesek"
++
++#: ../client/pk-console.c:754
++msgid "Could not get dependencies for this package"
++msgstr "Nem lehetett csomagfüggőséget megkapni e csomaghoz"
++
++#: ../client/pk-console.c:772
++msgid "Could not find details for this package"
++msgstr "Nem lehetett részletezőt találni e csomaghoz"
++
++#: ../client/pk-console.c:790
++msgid "Could not find the files for this package"
++msgstr "Nem lehetett fájlokat találni e csomaghoz"
++
++#: ../client/pk-console.c:870
++msgid "Package description"
++msgstr "Csomagleírás"
++
++#: ../client/pk-console.c:893
++msgid "Package files"
++msgstr "Csomagfájlok"
++
++#: ../client/pk-console.c:901
++msgid "No files"
++msgstr "Nincs fájl"
++
++#. get user input
++#: ../client/pk-console.c:933
++msgid "Okay to import key?"
++msgstr "Behozhatunk kulcsot?"
++
++#: ../client/pk-console.c:936
++msgid "Did not import key"
++msgstr "Nem hoztunk be kulcsot"
++
++#. get user input
++#: ../client/pk-console.c:976
++msgid "Do you agree?"
++msgstr "Egyetért?"
++
++#: ../client/pk-console.c:979
++msgid "Did not agree to licence, task will fail"
++msgstr "Nem egyezett meg az engedélyben, a munka elbukik"
++
++#: ../client/pk-console.c:1008
++msgid "The daemon crashed mid-transaction!"
++msgstr "A szolgáltatás összeomlott tranzakció közben!"
++
++#. header
++#: ../client/pk-console.c:1061
++msgid "PackageKit Console Interface"
++msgstr "PackageKit parancssori felület"
++
++#: ../client/pk-console.c:1061
++msgid "Subcommands:"
++msgstr "Részparancsok:"
++
++#: ../client/pk-console.c:1165
++#: ../client/pk-monitor.c:104
++#: ../src/pk-main.c:189
++msgid "Show extra debugging information"
++msgstr "Extra hibakereső adatok megjelenítése"
++
++#: ../client/pk-console.c:1167
++#: ../client/pk-monitor.c:106
++msgid "Show the program version and exit"
++msgstr "Programváltozat megmutatása és kilépés"
++
++#: ../client/pk-console.c:1169
++msgid "Set the filter, e.g. installed"
++msgstr "Szűrő beállítása, pl. telepítve"
++
++#: ../client/pk-console.c:1171
++msgid "Exit without waiting for actions to complete"
++msgstr "Kilépés cselekmény befejezésére várakozás nélkül"
++
++#: ../client/pk-console.c:1194
++msgid "Could not connect to system DBUS."
++msgstr "Nem lehetett kapcsolódni DBUS-hoz."
++
++#: ../client/pk-console.c:1288
++msgid "You need to specify a search type"
++msgstr "Meg kell adni a keresendő típust"
++
++#: ../client/pk-console.c:1293
++#: ../client/pk-console.c:1300
++#: ../client/pk-console.c:1307
++#: ../client/pk-console.c:1314
++#: ../client/pk-console.c:1421
++#: ../client/pk-console.c:1428
++#: ../client/pk-console.c:1435
++#: ../client/pk-console.c:1442
++msgid "You need to specify a search term"
++msgstr "Meg kell adni a keresendő kifejezést"
++
++#: ../client/pk-console.c:1319
++msgid "Invalid search type"
++msgstr "Érvénytelen típus"
++
++#: ../client/pk-console.c:1324
++msgid "You need to specify a package or file to install"
++msgstr "Meg kell adnia a telepítendő csomag  vagy fájl nevét"
++
++#: ../client/pk-console.c:1339
++msgid "You need to specify a type, key_id and package_id"
++msgstr "Meg kell adnia egy típust, kulcs azonosítót és csomag azonosítót"
++
++#: ../client/pk-console.c:1346
++msgid "You need to specify a package to remove"
++msgstr "Meg kell adnia egy eltávolítandó csomagot"
++
++#: ../client/pk-console.c:1353
++msgid "You need to specify a eula-id"
++msgstr "Meg kell adnia egy végfelhasználó azonosítót"
++
++#: ../client/pk-console.c:1369
++msgid "You need to specify a package name to resolve"
++msgstr "Meg kell adnia egy feloldandó csomagnevet"
++
++#: ../client/pk-console.c:1376
++#: ../client/pk-console.c:1383
++msgid "You need to specify a repo name"
++msgstr "Meg kell adnia egy tár nevét"
++
++#: ../client/pk-console.c:1390
++msgid "You need to specify a repo name/parameter and value"
++msgstr "Meg kell adnia egy tárnevet/paramétert és értéket"
++
++#: ../client/pk-console.c:1403
++msgid "You need to specify a time term"
++msgstr "Meg kell adnia egy időszakot"
++
++#: ../client/pk-console.c:1408
++msgid "You need to specify a correct role"
++msgstr "Meg kell adnia egy helyes szerepet"
++
++#: ../client/pk-console.c:1413
++msgid "Failed to get last time"
++msgstr "Nem sikerült megkapni az utolsó időt"
++
++#: ../client/pk-console.c:1449
++msgid "You need to specify a package to find the details for"
++msgstr "Meg kell adnia egy egy csomagot, amihez részletező keresendő"
++
++#: ../client/pk-console.c:1456
++msgid "You need to specify a package to find the files for"
++msgstr "Meg kell adnia egy csomagot, amihez fájlokat kell találni"
++
++#: ../client/pk-console.c:1503
++#, c-format
++msgid "Option '%s' not supported"
++msgstr "„%s” opció nem támogatott"
++
++#: ../client/pk-console.c:1514
++msgid "Command failed"
++msgstr "Parancs elbukott"
++
++#: ../client/pk-console.c:1518
++msgid "You don't have the necessary privileges for this operation"
++msgstr "Önnek nincs meg  szükséges jogosultsága e műveletre"
++
++#: ../client/pk-monitor.c:117
++msgid "PackageKit Monitor"
++msgstr "PackageKit figyelő"
++
++#: ../client/pk-import-desktop.c:293
++#: ../client/pk-import-specspo.c:169
++#, c-format
++msgid "Could not open database: %s"
++msgstr "Nem lehetett megnyitni %s adatbázist"
++
++#: ../client/pk-import-desktop.c:294
++#: ../client/pk-import-specspo.c:170
++msgid "You probably need to run this program as the root user"
++msgstr "E program valószínűleg rendszergazdaként futtatható"
++
++#: ../src/pk-main.c:83
++msgid "Startup failed due to security policies on this machine."
++msgstr "Indulás sikertelen a gép biztonsági szabályzata miatt."
++
++#: ../src/pk-main.c:84
++msgid "This can happen for two reasons:"
++msgstr "Két okból történet mehet:"
++
++#: ../src/pk-main.c:85
++msgid "The correct user is not launching the executable (usually root)"
++msgstr "A helyes használó nem indítja a futtathatót (rendszerint rendszergada)"
++
++#: ../src/pk-main.c:86
++msgid "The org.freedesktop.PackageKit.conf file is not installed in the system /etc/dbus-1/system.d directory"
++msgstr "Az org.freedesktop.PackageKit.conf a rendszert nem telepítették  a system /etc/dbus-1/system.d mappába"
++
++#: ../src/pk-main.c:185
++msgid "Packaging backend to use, e.g. dummy"
++msgstr "Használandó csomagoló háttér, pl. dummy"
++
++#: ../src/pk-main.c:187
++msgid "Daemonize and detach from the terminal"
++msgstr "Szolgálatatás és leválasztás terminálról"
++
++#: ../src/pk-main.c:191
++msgid "Disable the idle timer"
++msgstr "Tétlen időzítő kikapcsolása"
++
++#: ../src/pk-main.c:193
++msgid "Show version and exit"
++msgstr "Változat mutatása és kilépés"
++
++#: ../src/pk-main.c:195
++msgid "Exit after a small delay"
++msgstr "Kilépés rövid késleltetés után"
++
++#: ../src/pk-main.c:197
++msgid "Exit after the engine has loaded"
++msgstr "Kilépés a motor betöltése után"
++
++#: ../src/pk-main.c:207
++msgid "PackageKit service"
++msgstr "PackageKit szolgáltatás"
++
++#: ../src/pk-main.c:233
++msgid "Cannot connect to the system bus"
++msgstr "Nem lehetett csatlakozni a rendszerbuszhoz"
++
++#: ../src/pk-main.c:273
++#, c-format
++msgid "Error trying to start: %s\n"
++msgstr "Hiba %s indításakor\n"
++
+diff --git a/policy/org.freedesktop.packagekit.policy.in b/policy/org.freedesktop.packagekit.policy.in
+index 32efce7..4c4607d 100644
+--- a/policy/org.freedesktop.packagekit.policy.in
++++ b/policy/org.freedesktop.packagekit.policy.in
+@@ -133,5 +133,17 @@
+       <allow_active>yes</allow_active>
+     </defaults>
+   </action>
++
++  <action id="org.freedesktop.packagekit.set-proxy">
++    <_description>Set network proxy</_description>
++    <_message>Authentication is required to set the network proxy used for downloading packages</_message>
++    <icon_name>applications-internet</icon_name>
++    <vendor_url>http://www.packagekit.org/pk-reference.html#methods-set-proxy</vendor_url>
++    <defaults>
++      <allow_inactive>no</allow_inactive>
++      <allow_active>yes</allow_active>
++    </defaults>
++  </action>
++
+ </policyconfig>
+diff --git a/python/packagekit/daemonBackend.py b/python/packagekit/daemonBackend.py
+index 5253b39..9fd627a 100644
+--- a/python/packagekit/daemonBackend.py
++++ b/python/packagekit/daemonBackend.py
+@@ -325,13 +325,13 @@ class PackageKitBaseBackend(dbus.service.Object):
+     @PKSignalHouseKeeper
+     @dbus.service.signal(dbus_interface=PACKAGEKIT_DBUS_INTERFACE,
+-                         signature='sssssss')
+-    def RepoSignatureRequired(self,repo_name,key_url,key_userid,key_id,key_fingerprint,key_timestamp,key_type):
++                         signature='ssssssss')
++    def RepoSignatureRequired(self,id,repo_name,key_url,key_userid,key_id,key_fingerprint,key_timestamp,key_type):
+         '''
+         send 'repo-signature-required' signal:
+         '''
+         pklog.info("RepoSignatureRequired (%s, %s, %s, %s, %s, %s, %s, %s)" %
+-                   (repo_name,key_url,key_userid,key_id,key_fingerprint,key_timestamp,key_type))
++                   (id,repo_name,key_url,key_userid,key_id,key_fingerprint,key_timestamp,key_type))
+ #
+@@ -658,8 +658,9 @@ class PackageKitBaseBackend(dbus.service.Object):
+         '''
+         Implement the {backend}-remove functionality
+         '''
+-        pklog.info("RemovePackages(%s, %s, %s)" % (package[0], allowdep, autoremove))
+-        self.doRemovePackages(package, allowdep, autoremove)
++        pklog.info("RemovePackages(%s, %s, %s)" % (packages, allowdep,
++                                                   autoremove))
++        self.doRemovePackages(packages, allowdep, autoremove)
+     def doRemovePackages(self, packages, allowdep, autoremove):
+         '''
+diff --git a/src/pk-backend-spawn.c b/src/pk-backend-spawn.c
+index f9c9f12..2bd416d 100644
+--- a/src/pk-backend-spawn.c
++++ b/src/pk-backend-spawn.c
+@@ -316,8 +316,8 @@ pk_backend_spawn_parse_stdout (PkBackendSpawn *backend_spawn, const gchar *line)
+               pk_backend_set_percentage (backend_spawn->priv->backend, PK_BACKEND_PERCENTAGE_INVALID);
+       } else if (pk_strequal (command, "repo-signature-required")) {
+-              if (size != 9+99) {
+-                      pk_error ("invalid command '%s'", command);
++              if (size != 9) {
++                      pk_warning ("invalid command '%s'", command);
+                       ret = FALSE;
+                       goto out;
+               }
+diff --git a/src/pk-backend.c b/src/pk-backend.c
+index 37ed024..f0f245f 100644
+--- a/src/pk-backend.c
++++ b/src/pk-backend.c
+@@ -1484,8 +1484,7 @@ pk_backend_finished (PkBackend *backend)
+            backend->priv->role == PK_ROLE_ENUM_REMOVE_PACKAGES ||
+            backend->priv->role == PK_ROLE_ENUM_UPDATE_PACKAGES)) {
+               pk_backend_message (backend, PK_MESSAGE_ENUM_DAEMON,
+-                                  "Backends need to send a Package() for this role!");
+-              return FALSE;
++                                  "Backends should send a Package() for this role!");
+       }
+       /* if we set an error code notifier, clear */
+diff --git a/src/pk-backend.h b/src/pk-backend.h
+index fb17e3c..a7ba754 100644
+--- a/src/pk-backend.h
++++ b/src/pk-backend.h
+@@ -256,7 +256,7 @@ typedef struct {
+       void            (*update_system)                (PkBackend      *backend);
+       void            (*what_provides)                (PkBackend      *backend,
+                                                        PkFilterEnum    filters,
+-                                                       PkProvidesEnum provide,
++                                                       PkProvidesEnum  provides,
+                                                        const gchar    *search);
+       gpointer        padding[10];
+ } PkBackendDesc;
+diff --git a/src/pk-engine.c b/src/pk-engine.c
+index 028a0d0..14ecf41 100644
+--- a/src/pk-engine.c
++++ b/src/pk-engine.c
+@@ -154,6 +154,8 @@ pk_engine_error_get_type (void)
+               static const GEnumValue values[] =
+               {
+                       ENUM_ENTRY (PK_ENGINE_ERROR_INVALID_STATE, "InvalidState"),
++                      ENUM_ENTRY (PK_ENGINE_ERROR_REFUSED_BY_POLICY, "RefusedByPolicy"),
++                      ENUM_ENTRY (PK_ENGINE_ERROR_CANNOT_SET_PROXY, "CannotSetProxy"),
+                       { 0, NULL, NULL }
+               };
+               etype = g_enum_register_static ("PkEngineError", values);
+@@ -502,6 +504,47 @@ pk_engine_suggest_daemon_quit (PkEngine *engine, GError **error)
+ }
+ /**
++ * pk_engine_set_proxy:
++ **/
++void
++pk_engine_set_proxy (PkEngine *engine, const gchar *proxy_http, const gchar *proxy_ftp, DBusGMethodInvocation *context)
++{
++      gboolean ret;
++      GError *error;
++      gchar *sender = NULL;
++      gchar *error_detail = NULL;
++
++      g_return_if_fail (PK_IS_ENGINE (engine));
++
++      pk_debug ("SetProxy method called: %s, %s", proxy_http, proxy_ftp);
++
++      /* check if the action is allowed from this client - if not, set an error */
++      sender = dbus_g_method_get_sender (context);
++
++      /* use security model to get auth */
++      ret = pk_security_action_is_allowed (engine->priv->security, sender, FALSE, PK__ROLE_ENUM_SET_PROXY, &error_detail);
++      if (!ret) {
++              error = g_error_new (PK_ENGINE_ERROR, PK_ENGINE_ERROR_REFUSED_BY_POLICY, "%s", error_detail);
++              dbus_g_method_return_error (context, error);
++              goto out;
++      }
++
++      /* try to set the new proxy */
++      ret = pk_backend_set_proxy (engine->priv->backend, proxy_http, proxy_ftp);
++      if (!ret) {
++              error = g_error_new (PK_ENGINE_ERROR, PK_ENGINE_ERROR_CANNOT_SET_PROXY, "%s", "setting the proxy failed");
++              dbus_g_method_return_error (context, error);
++              goto out;
++      }
++
++      /* all okay */
++      dbus_g_method_return (context);
++out:
++      g_free (sender);
++      g_free (error_detail);
++}
++
++/**
+  * pk_engine_class_init:
+  * @klass: The PkEngineClass
+  **/
+diff --git a/src/pk-engine.h b/src/pk-engine.h
+index c59b1f3..668451f 100644
+--- a/src/pk-engine.h
++++ b/src/pk-engine.h
+@@ -57,9 +57,12 @@ typedef enum
+ {
+       PK_ENGINE_ERROR_DENIED,
+       PK_ENGINE_ERROR_INVALID_STATE,
++      PK_ENGINE_ERROR_REFUSED_BY_POLICY,
++      PK_ENGINE_ERROR_CANNOT_SET_PROXY,
+       PK_ENGINE_ERROR_LAST
+ } PkEngineError;
++
+ GQuark                 pk_engine_error_quark                  (void);
+ GType          pk_engine_error_get_type               (void) G_GNUC_CONST;
+ GType          pk_engine_get_type                     (void) G_GNUC_CONST;
+@@ -100,6 +103,10 @@ gboolean   pk_engine_state_has_changed            (PkEngine       *engine,
+                                                        GError         **error);
+ gboolean       pk_engine_suggest_daemon_quit          (PkEngine       *engine,
+                                                        GError         **error);
++void           pk_engine_set_proxy                    (PkEngine       *engine,
++                                                       const gchar    *proxy_http,
++                                                       const gchar    *proxy_ftp,
++                                                       DBusGMethodInvocation *context);
+ G_END_DECLS
+diff --git a/src/pk-interface.xml b/src/pk-interface.xml
+index e9e74e1..7290bbe 100644
+--- a/src/pk-interface.xml
++++ b/src/pk-interface.xml
+@@ -33,6 +33,11 @@
+     <method name="GetNetworkState">
+       <arg type="s" name="state" direction="out"/>
+     </method>
++    <method name="SetProxy">
++      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
++      <arg type="s" name="proxy_http" direction="in"/>
++      <arg type="s" name="proxy_ftp" direction="in"/>
++    </method>
+     <signal name="TransactionListChanged">
+       <arg type="as" name="transactions" direction="out"/>
+diff --git a/src/pk-security-polkit.c b/src/pk-security-polkit.c
+index 9abf992..81332d0 100644
+--- a/src/pk-security-polkit.c
++++ b/src/pk-security-polkit.c
+@@ -128,6 +128,9 @@ pk_security_role_to_action (PkSecurity *security, gboolean trusted, PkRoleEnum r
+               policy = "org.freedesktop.packagekit.repo-change";
+       } else if (role == PK_ROLE_ENUM_REFRESH_CACHE) {
+               policy = "org.freedesktop.packagekit.refresh-cache";
++      /* PRIVATE: not actually roles */
++      } else if (role == PK__ROLE_ENUM_SET_PROXY) {
++              policy = "org.freedesktop.packagekit.refresh-cache";
+       }
+       return policy;
+ }
+diff --git a/src/pk-security.h b/src/pk-security.h
+index 3432095..eb55932 100644
+--- a/src/pk-security.h
++++ b/src/pk-security.h
+@@ -34,6 +34,9 @@ G_BEGIN_DECLS
+ #define PK_IS_SECURITY_CLASS(k)               (G_TYPE_CHECK_CLASS_TYPE ((k), PK_TYPE_SECURITY))
+ #define PK_SECURITY_GET_CLASS(o)      (G_TYPE_INSTANCE_GET_CLASS ((o), PK_TYPE_SECURITY, PkSecurityClass))
++/* FIXME: not actually a role */
++#define PK__ROLE_ENUM_SET_PROXY               1 << 31
++
+ typedef struct PkSecurityPrivate PkSecurityPrivate;
+ typedef struct
+diff --git a/src/pk-transaction-db.c b/src/pk-transaction-db.c
+index 7aa183f..d42bc7a 100644
+--- a/src/pk-transaction-db.c
++++ b/src/pk-transaction-db.c
+@@ -46,7 +46,12 @@ static void     pk_transaction_db_init              (PkTransactionDb      *tdb);
+ static void     pk_transaction_db_finalize    (GObject        *object);
+ #define PK_TRANSACTION_DB_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PK_TYPE_TRANSACTION_DB, PkTransactionDbPrivate))
++
++#if PK_BUILD_LOCAL
++#define PK_TRANSACTION_DB_FILE                "./transactions.db"
++#else
+ #define PK_TRANSACTION_DB_FILE                PK_DB_DIR "/transactions.db"
++#endif
+ struct PkTransactionDbPrivate
+ {
+diff --git a/src/pk-transaction-list.c b/src/pk-transaction-list.c
+index 0921c7c..f325f94 100644
+--- a/src/pk-transaction-list.c
++++ b/src/pk-transaction-list.c
+@@ -89,7 +89,6 @@ pk_transaction_list_get_from_transaction (PkTransactionList *tlist, PkTransactio
+       /* find the runner with the transaction ID */
+       length = tlist->priv->array->len;
+-      pk_debug ("length = %i", length);
+       for (i=0; i<length; i++) {
+               item = (PkTransactionItem *) g_ptr_array_index (tlist->priv->array, i);
+               if (item->transaction == transaction) {
+@@ -352,28 +351,29 @@ gchar **
+ pk_transaction_list_get_array (PkTransactionList *tlist)
+ {
+       guint i;
+-      guint count = 0;
+       guint length;
++      GPtrArray *parray;
+       gchar **array;
+       PkTransactionItem *item;
+       g_return_val_if_fail (PK_IS_TRANSACTION_LIST (tlist), NULL);
++      /* use a temp array, as not all are in progress */
++      parray = g_ptr_array_new ();
++
+       /* find all the transactions in progress */
+       length = tlist->priv->array->len;
+-
+-      /* create new strv list */
+-      array = g_new0 (gchar *, length + 1);
+-
+-      pk_debug ("%i active transactions", length);
+       for (i=0; i<length; i++) {
+               item = (PkTransactionItem *) g_ptr_array_index (tlist->priv->array, i);
+-              /* only return in the list if it worked */
+-              if (item->committed && item->finished == FALSE) {
+-                      array[count] = g_strdup (item->tid);
+-                      count++;
++              /* only return in the list if its committed and not finished */
++              if (item->committed && !item->finished) {
++                      g_ptr_array_add (parray, g_strdup (item->tid));
+               }
+       }
++      pk_debug ("%i transactions in list, %i active", length, parray->len);
++      array = pk_ptr_array_to_argv (parray);
++      g_ptr_array_free (parray, TRUE);
++
+       return array;
+ }
+diff --git a/src/pk-transaction.c b/src/pk-transaction.c
+index 07ffdee..15faed3 100644
+--- a/src/pk-transaction.c
++++ b/src/pk-transaction.c
+@@ -71,6 +71,7 @@ struct PkTransactionPrivate
+       PkStatusEnum             status;
+       gboolean                 finished;
+       gboolean                 running;
++      gboolean                 has_been_run;
+       gboolean                 allow_cancel;
+       gboolean                 emit_eula_required;
+       gboolean                 emit_signature_required;
+@@ -798,6 +799,7 @@ pk_transaction_set_running (PkTransaction *transaction)
+       /* mark running */
+       transaction->priv->running = TRUE;
++      transaction->priv->has_been_run = TRUE;
+       /* set all possible arguments for backend */
+       pk_backend_set_bool (priv->backend, "force", priv->cached_force);
+@@ -1152,11 +1154,17 @@ pk_transaction_cancel (PkTransaction *transaction, GError **error)
+       g_return_val_if_fail (transaction->priv->tid != NULL, FALSE);
+       pk_debug ("Cancel method called");
+-      /* check to see if we are trying to cancel a non-running task */
+-      if (!transaction->priv->running) {
+-              g_set_error (error, PK_TRANSACTION_ERROR, PK_TRANSACTION_ERROR_NOT_RUNNING,
+-                           "cancelling a non-running transaction");
+-              return FALSE;
++
++      /* if it's never been run, just remove this transaction from the list */
++      if (!transaction->priv->has_been_run) {
++              pk_transaction_list_remove (transaction->priv->transaction_list, transaction);
++              return TRUE;
++      }
++
++      /* if it's finished, cancelling will have no action */
++      if (transaction->priv->finished) {
++              pk_warning ("No point trying to cancel a finished transaction, ignoring");
++              return TRUE;
+       }
+       /* not implemented yet */
+@@ -2871,7 +2879,7 @@ pk_transaction_what_provides (PkTransaction *transaction, const gchar *filter, c
+               return;
+       }
+-      provides = pk_role_enum_from_text (type);
++      provides = pk_provides_enum_from_text (type);
+       if (provides == PK_PROVIDES_ENUM_UNKNOWN) {
+               error = g_error_new (PK_TRANSACTION_ERROR, PK_TRANSACTION_ERROR_INVALID_PROVIDE,
+                                    "provide type '%s' not found", type);
+@@ -3011,6 +3019,7 @@ pk_transaction_init (PkTransaction *transaction)
+       transaction->priv = PK_TRANSACTION_GET_PRIVATE (transaction);
+       transaction->priv->finished = FALSE;
+       transaction->priv->running = FALSE;
++      transaction->priv->has_been_run = FALSE;
+       transaction->priv->allow_cancel = FALSE;
+       transaction->priv->emit_eula_required = FALSE;
+       transaction->priv->emit_signature_required = FALSE;
+diff --git a/tools/add-error-enum.sh b/tools/add-error-enum.sh
+index f78c891..6521e69 100755
+--- a/tools/add-error-enum.sh
++++ b/tools/add-error-enum.sh
+@@ -7,5 +7,5 @@
+ # the Free Software Foundation; either version 2 of the License, or
+ # (at your option) any later version.
+-$EDITOR docs/spec/pk-introduction.xml libpackagekit/pk-enum.h libpackagekit/pk-enum.c ../gnome-packagekit/src/gpk-common.c
++$EDITOR docs/spec/pk-concepts.xml libpackagekit/pk-enum.h libpackagekit/pk-enum.c ../gnome-packagekit/src/gpk-common.c
+diff --git a/tools/rpmbuild.sh b/tools/rpmbuild.sh
+deleted file mode 100755
+index ebbd8f7..0000000
+--- a/tools/rpmbuild.sh
++++ /dev/null
+@@ -1,19 +0,0 @@
+-#!/bin/sh
+-# Copyright (C) 2008 Richard Hughes <richard@hughsie.com>
+-#
+-# Licensed under the GNU General Public License Version 2
+-# 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 2 of the License, or
+-# (at your option) any later version.
+-
+-sudo echo "Build!"
+-#autobuild.sh all PolicyKit
+-#sudo auto_refresh_from_repo.sh
+-#autobuild.sh all PolicyKit-gnome
+-#sudo auto_refresh_from_repo.sh
+-autobuild.sh all PackageKit force
+-sudo auto_refresh_from_repo.sh
+-autobuild.sh all gnome-packagekit force
+-sudo auto_refresh_from_repo.sh
+-
diff --git a/packages/packagekit/files/d1e096c3267c1c9492041382b954e9327bc8bbec.patch b/packages/packagekit/files/d1e096c3267c1c9492041382b954e9327bc8bbec.patch
deleted file mode 100644 (file)
index f050a50..0000000
+++ /dev/null
@@ -1,2938 +0,0 @@
-diff --git a/backends/alpm/pk-backend-alpm.c b/backends/alpm/pk-backend-alpm.c
-index 3270e42..45e7a44 100644
---- a/backends/alpm/pk-backend-alpm.c
-+++ b/backends/alpm/pk-backend-alpm.c
-@@ -895,7 +895,7 @@ backend_get_repo_list (PkBackend *backend, PkFilterEnum filters)
- static gboolean
- backend_install_files_thread (PkBackend *backend)
- {
--      pk_backend_no_percentage_updates (backend);
-+      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
-       gchar **full_paths = pk_backend_get_strv (backend, "full_paths");
-@@ -1050,7 +1050,7 @@ backend_install_packages (PkBackend *backend, gchar **package_ids)
- static gboolean
- backend_refresh_cache_thread (PkBackend *backend)
- {
--      pk_backend_no_percentage_updates (backend);
-+      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
-       if (alpm_trans_init (PM_TRANS_TYPE_SYNC, PM_TRANS_FLAG_NOSCRIPTLET, cb_trans_evt, cb_trans_conv, cb_trans_progress) != 0) {
-               pk_backend_error_code (backend, PK_ERROR_ENUM_TRANSACTION_ERROR, alpm_strerror (pm_errno));
-diff --git a/backends/apt/pk-apt-build-db.cpp b/backends/apt/pk-apt-build-db.cpp
-index d47c348..885275d 100644
---- a/backends/apt/pk-apt-build-db.cpp
-+++ b/backends/apt/pk-apt-build-db.cpp
-@@ -40,7 +40,7 @@ void apt_build_db(PkBackend * backend, sqlite3 *db)
-       sqlite3_stmt *package = NULL;
-       pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY);
--      pk_backend_no_percentage_updates(backend);
-+      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
-       sdir = g_build_filename(_config->Find("Dir").c_str(),_config->Find("Dir::State").c_str(),_config->Find("Dir::State::lists").c_str(), NULL);
-       dir = g_dir_open(sdir,0,&error);
-diff --git a/backends/apt/pk-sqlite-pkg-cache.cpp b/backends/apt/pk-sqlite-pkg-cache.cpp
-index 770fcdf..1bf9a50 100644
---- a/backends/apt/pk-sqlite-pkg-cache.cpp
-+++ b/backends/apt/pk-sqlite-pkg-cache.cpp
-@@ -81,7 +81,7 @@ sqlite_search_packages_thread (PkBackend *backend)
-       const gchar *search;
-       pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY);
--      pk_backend_no_percentage_updates(backend);
-+      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
-       type = pk_backend_get_uint (backend, "type");
-       search = pk_backend_get_string (backend, "search");
-@@ -176,7 +176,7 @@ sqlite_get_details_thread (PkBackend *backend)
-       }
-       pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY);
--      pk_backend_no_percentage_updates(backend);
-+      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
-       pk_debug("finding %s", pi->name);
-diff --git a/backends/box/pk-backend-box.c b/backends/box/pk-backend-box.c
-index b7b8167..9263781 100644
---- a/backends/box/pk-backend-box.c
-+++ b/backends/box/pk-backend-box.c
-@@ -138,7 +138,7 @@ backend_find_packages_thread (PkBackend *backend)
-               filter_box = filter_box | PKG_SEARCH_DETAILS;
-       }
--      pk_backend_no_percentage_updates (backend);
-+      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
-       db = db_open();
-diff --git a/backends/dummy/pk-backend-dummy.c b/backends/dummy/pk-backend-dummy.c
-index 49d4e5a..2df445e 100644
---- a/backends/dummy/pk-backend-dummy.c
-+++ b/backends/dummy/pk-backend-dummy.c
-@@ -254,7 +254,7 @@ static void
- backend_get_updates (PkBackend *backend, PkFilterEnum filters)
- {
-       pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
--      pk_backend_no_percentage_updates (backend);
-+      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
-       /* check network state */
-       if (!pk_backend_is_online (backend)) {
-               pk_backend_error_code (backend, PK_ERROR_ENUM_NO_NETWORK, "Cannot check when offline");
-@@ -268,6 +268,8 @@ static gboolean
- backend_install_timeout (gpointer data)
- {
-       PkBackend *backend = (PkBackend *) data;
-+      guint sub_percent;
-+
-       if (_progress_percentage == 100) {
-               pk_backend_finished (backend);
-               return FALSE;
-@@ -283,9 +285,18 @@ backend_install_timeout (gpointer data)
-               pk_backend_package (backend, PK_INFO_ENUM_INSTALLING,
-                                   "gtkhtml2-devel;2.19.1-0.fc8;i386;fedora",
-                                   "Devel files for gtkhtml");
-+              /* this duplicate package should be ignored */
-+              pk_backend_package (backend, PK_INFO_ENUM_INSTALLING,
-+                                  "gtkhtml2-devel;2.19.1-0.fc8;i386;fedora", NULL);
-               pk_backend_set_status (backend, PK_STATUS_ENUM_INSTALL);
-       }
--      _progress_percentage += 10;
-+      if (_progress_percentage > 30 && _progress_percentage < 50) {
-+              sub_percent = ((gfloat) (_progress_percentage - 30.0f) / 20.0f) * 100.0f;
-+              pk_backend_set_sub_percentage (backend, sub_percent);
-+      } else {
-+              pk_backend_set_sub_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
-+      }
-+      _progress_percentage += 1;
-       pk_backend_set_percentage (backend, _progress_percentage);
-       return TRUE;
- }
-@@ -348,7 +359,7 @@ backend_install_packages (PkBackend *backend, gchar **package_ids)
-       pk_backend_package (backend, PK_INFO_ENUM_DOWNLOADING,
-                           "gtkhtml2;2.19.1-4.fc8;i386;fedora",
-                           "An HTML widget for GTK+ 2.0");
--      _signal_timeout = g_timeout_add (1000, backend_install_timeout, backend);
-+      _signal_timeout = g_timeout_add (100, backend_install_timeout, backend);
- }
- /**
-@@ -526,7 +537,7 @@ backend_search_name_timeout (gpointer data)
- static void
- backend_search_name (PkBackend *backend, PkFilterEnum filters, const gchar *search)
- {
--      pk_backend_no_percentage_updates (backend);
-+      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
-       pk_backend_set_allow_cancel (backend, TRUE);
-       pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
-       _signal_timeout = g_timeout_add (2000, backend_search_name_timeout, backend);
-diff --git a/backends/opkg/pk-backend-opkg.c b/backends/opkg/pk-backend-opkg.c
-index ecc97be..7649bab 100644
---- a/backends/opkg/pk-backend-opkg.c
-+++ b/backends/opkg/pk-backend-opkg.c
-@@ -155,6 +155,38 @@ pk_opkg_progress_cb (opkg_t *opkg, const opkg_progress_data_t *pdata, void *data
-               return;
-       pk_backend_set_percentage (backend, pdata->percentage);
-+      if (pdata->package)
-+      {
-+              gchar *uid;
-+              opkg_package_t *pkg = pdata->package;
-+              gint status = PK_INFO_ENUM_UNKNOWN;
-+
-+              uid = g_strdup_printf ("%s;%s;%s;",
-+                      pkg->name, pkg->version, pkg->architecture);
-+
-+              if (pdata->action == OPKG_DOWNLOAD)
-+                      status = PK_INFO_ENUM_DOWNLOADING;
-+              else if (pdata->action == OPKG_INSTALL)
-+                      status = PK_INFO_ENUM_INSTALLING;
-+              else if (pdata->action == OPKG_REMOVE)
-+                      status = PK_INFO_ENUM_REMOVING;
-+
-+              pk_backend_package (backend, status, uid, pkg->description);
-+              g_free (uid);
-+      }
-+
-+      switch (pdata->action)
-+      {
-+      case OPKG_DOWNLOAD:
-+              pk_backend_set_status (backend, PK_STATUS_ENUM_DOWNLOAD);
-+              break;
-+      case OPKG_INSTALL:
-+              pk_backend_set_status (backend, PK_STATUS_ENUM_INSTALL);
-+              break;
-+      case OPKG_REMOVE:
-+              pk_backend_set_status (backend, PK_STATUS_ENUM_REMOVE);
-+              break;
-+      }
- }
- static gboolean
-@@ -163,8 +195,12 @@ backend_refresh_cache_thread (PkBackend *backend)
-       int ret;
-       ret = opkg_update_package_lists (opkg, pk_opkg_progress_cb, backend);
-+
-       if (ret) {
--              opkg_unknown_error (backend, ret, "Refreshing cache");
-+              if (ret == OPKG_DOWNLOAD_FAILED)
-+                      pk_backend_error_code (backend, PK_ERROR_ENUM_REPO_NOT_AVAILABLE, NULL);
-+              else
-+                      opkg_unknown_error (backend, ret, "Refreshing cache");
-       }
-       pk_backend_finished (backend);
-@@ -178,7 +214,7 @@ static void
- backend_refresh_cache (PkBackend *backend, gboolean force)
- {
-       pk_backend_set_status (backend, PK_STATUS_ENUM_REFRESH_CACHE);
--      pk_backend_no_percentage_updates (backend);
-+      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
-       pk_backend_thread_create (backend, backend_refresh_cache_thread);
-@@ -279,7 +315,7 @@ backend_search_name (PkBackend *backend, PkFilterEnum filters, const gchar *sear
-       pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
--      pk_backend_no_percentage_updates (backend);
-+      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
-       params = g_new0 (SearchParams, 1);
-       params->filters = filters;
-@@ -301,7 +337,7 @@ backend_search_description (PkBackend *backend, PkFilterEnum filters, const gcha
-       pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
--      pk_backend_no_percentage_updates (backend);
-+      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
-       params = g_new0 (SearchParams, 1);
-       params->filters = filters;
-@@ -320,7 +356,7 @@ backend_search_group (PkBackend *backend, PkFilterEnum filters, const gchar *sea
-       pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
--      pk_backend_no_percentage_updates (backend);
-+      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
-       params = g_new0 (SearchParams, 1);
-       params->filters = filters;
-@@ -337,30 +373,52 @@ static gboolean
- backend_install_packages_thread (PkBackend *backend)
- {
-       PkPackageId *pi;
--      gint err;
--      const gchar *package_id;
-+      gint err, i;
-+      gchar **package_ids;
--      package_id = pk_backend_get_string (backend, "pkid");
--      pk_backend_package (backend, PK_INFO_ENUM_INSTALLING, package_id, NULL);
-+      package_ids = pk_backend_get_strv (backend, "pkids");
--      pi = pk_package_id_new_from_string (package_id);
-+      err = 0;
-+
-+      for (i = 0; package_ids[i]; i++)
-+      {
-+              pk_backend_package (backend, PK_INFO_ENUM_INSTALLING, package_ids[0], NULL);
--      err = opkg_install_package (opkg, pi->name, pk_opkg_progress_cb, backend);
--      if (err != 0)
--              opkg_unknown_error (backend, err, "Install");
-+              pi = pk_package_id_new_from_string (package_ids[0]);
-+
-+              err = opkg_install_package (opkg, pi->name, pk_opkg_progress_cb, backend);
-+              switch (err)
-+              {
-+              case OPKG_NO_ERROR:
-+                      break;
-+              case OPKG_DEPENDANCIES_FAILED:
-+                      pk_backend_error_code (backend, PK_ERROR_ENUM_DEP_RESOLUTION_FAILED, NULL);
-+                      break;
-+              case OPKG_PACKAGE_ALREADY_INSTALLED:
-+                      pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_ALREADY_INSTALLED, NULL);
-+                      break;
-+              case OPKG_PACKAGE_NOT_AVAILABLE:
-+                      pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_NOT_FOUND, NULL);
-+                      break;
-+              default:
-+                      opkg_unknown_error (backend, err, "Install");
-+              }
-+              pk_package_id_free (pi);
-+              if (err != 0)
-+                      break;
-+      }
--      pk_package_id_free (pi);
-       pk_backend_finished (backend);
-       return (err == 0);
- }
- static void
--backend_install_packages (PkBackend *backend, gchar **package_id)
-+backend_install_packages (PkBackend *backend, gchar **package_ids)
- {
--      pk_backend_no_percentage_updates (backend);
-+      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
-       pk_backend_set_status (backend, PK_STATUS_ENUM_INSTALL);
--      pk_backend_set_string (backend, "pkid", package_id[0]);
-+      pk_backend_set_strv (backend, "pkids", package_ids);
-       pk_backend_thread_create (backend, backend_install_packages_thread);
- }
-@@ -369,7 +427,7 @@ static gboolean
- backend_remove_packages_thread (PkBackend *backend)
- {
-       PkPackageId *pi;
--      gint err;
-+      gint err, i;
-       gchar **package_ids;
-       gboolean allow_deps;
-       gboolean autoremove;
-@@ -382,19 +440,34 @@ backend_remove_packages_thread (PkBackend *backend)
-       autoremove = GPOINTER_TO_INT (data[2]);
-       g_free (data);
--      pi = pk_package_id_new_from_string (package_ids[0]);
--      pk_backend_package (backend, PK_INFO_ENUM_REMOVING, package_ids[0], NULL);
--
-       opkg_set_option (opkg, "autoremove", &autoremove);
-       opkg_set_option (opkg, "force_removal_of_dependent_packages", &allow_deps);
--      err = opkg_remove_package (opkg, pi->name, pk_opkg_progress_cb, backend);
-+      err = 0;
--      /* TODO: improve error reporting */
--      if (err != 0)
--              opkg_unknown_error (backend, err, "Remove");
-+      for (i = 0; package_ids[i]; i++)
-+      {
-+              pi = pk_package_id_new_from_string (package_ids[0]);
-+              pk_backend_package (backend, PK_INFO_ENUM_REMOVING, package_ids[0], NULL);
-+
-+              err = opkg_remove_package (opkg, pi->name, pk_opkg_progress_cb, backend);
-+
-+              switch (err)
-+              {
-+              case OPKG_NO_ERROR:
-+                      break;
-+              case OPKG_PACKAGE_NOT_INSTALLED:
-+                      pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_NOT_INSTALLED, NULL);
-+                      break;
-+              default:
-+                      opkg_unknown_error (backend, err, "Remove");
-+              }
-+              pk_package_id_free (pi);
-+
-+              if (err != 0)
-+                      break;
-+      }
--      pk_package_id_free (pi);
-       pk_backend_finished (backend);
-       return (err == 0);
- }
-@@ -405,7 +478,7 @@ backend_remove_packages (PkBackend *backend, gchar **package_ids, gboolean allow
-       gpointer *params;
-       pk_backend_set_status (backend, PK_STATUS_ENUM_REMOVE);
--      pk_backend_no_percentage_updates (backend);
-+      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
-       /* params is a small array we can pack our thread parameters into */
-       params = g_new0 (gpointer, 2);
-@@ -450,7 +523,7 @@ static void
- backend_update_system (PkBackend *backend)
- {
-       pk_backend_set_status (backend, PK_STATUS_ENUM_UPDATE);
--      pk_backend_no_percentage_updates (backend);
-+      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
-       pk_backend_thread_create (backend, backend_update_system_thread);
- }
-@@ -478,8 +551,14 @@ backend_update_package_thread (PkBackend *backend)
-       }
-       err = opkg_upgrade_package (opkg, pi->name, pk_opkg_progress_cb, backend);
--
--      if (err != 0) {
-+      switch (err)
-+      {
-+      case OPKG_NO_ERROR:
-+              break;
-+      case OPKG_PACKAGE_NOT_INSTALLED:
-+              pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_NOT_INSTALLED, NULL);
-+              break;
-+      default:
-               opkg_unknown_error (backend, err, "Update package");
-       }
-@@ -494,7 +573,7 @@ backend_update_packages (PkBackend *backend, gchar **package_ids)
-       gint i;
-       pk_backend_set_status (backend, PK_STATUS_ENUM_UPDATE);
--      pk_backend_no_percentage_updates (backend);
-+      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
-       for (i = 0; package_ids[i]; i++) {
-               pk_backend_set_string (backend, "pkgid", package_ids[i]);
-@@ -536,7 +615,7 @@ static void
- backend_get_updates (PkBackend *backend, PkFilterEnum filters)
- {
-       pk_backend_set_status (backend, PK_STATUS_ENUM_UPDATE);
--      pk_backend_no_percentage_updates (backend);
-+      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
-       pk_backend_thread_create (backend, backend_get_updates_thread);
- }
-@@ -572,19 +651,26 @@ backend_get_details_thread (PkBackend *backend)
-       if (pi == NULL)
-       {
-               pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_ID_INVALID, "invalid package id");
--              pk_package_id_free (pi);
-+              pk_backend_finished (backend);
-               return FALSE;
-       }
-       pkg = opkg_find_package (opkg, pi->name, pi->version, pi->arch, pi->data);
-+      pk_package_id_free (pi);
-+
-+      if (!pkg)
-+      {
-+              pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_NOT_FOUND, NULL);
-+              pk_backend_finished (backend);
-+              return FALSE;
-+      }
-       newid = g_strdup_printf ("%s;%s;%s;%s", pkg->name, pkg->version, pkg->architecture, pkg->repository);
-       pk_backend_details (backend, newid, NULL, 0, pkg->description, pkg->url, pkg->size);
-       g_free (newid);
--      pk_package_id_free (pi);
-       pk_backend_finished (backend);
-       return TRUE;
- }
-@@ -592,7 +678,7 @@ backend_get_details_thread (PkBackend *backend)
- static void
- backend_get_details (PkBackend *backend, const gchar *package_id)
- {
--      pk_backend_no_percentage_updates (backend);
-+      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
-       pk_backend_thread_create (backend, backend_get_details_thread);
- }
-diff --git a/backends/test/pk-backend-test-dbus.c b/backends/test/pk-backend-test-dbus.c
-index 5dfea32..76686dc 100644
---- a/backends/test/pk-backend-test-dbus.c
-+++ b/backends/test/pk-backend-test-dbus.c
-@@ -36,7 +36,7 @@ static void
- backend_search_name (PkBackend *backend, PkFilterEnum filters, const gchar *search)
- {
-       pk_backend_set_allow_cancel (backend, TRUE);
--      pk_backend_no_percentage_updates (backend);
-+      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
-       pk_backend_dbus_search_name (dbus, filters, search);
- }
-diff --git a/backends/test/pk-backend-test-spawn.c b/backends/test/pk-backend-test-spawn.c
-index 2958c05..584f44c 100644
---- a/backends/test/pk-backend-test-spawn.c
-+++ b/backends/test/pk-backend-test-spawn.c
-@@ -35,7 +35,7 @@ backend_search_name (PkBackend *backend, PkFilterEnum filters, const gchar *sear
- {
-       gchar *filters_text;
-       pk_backend_set_allow_cancel (backend, TRUE);
--      pk_backend_no_percentage_updates (backend);
-+      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
-       filters_text = pk_filter_enums_to_text (filters);
-       pk_backend_spawn_helper (spawn, "search-name.sh", filters_text, search, NULL);
-       g_free (filters_text);
-diff --git a/backends/test/pk-backend-test-succeed.c b/backends/test/pk-backend-test-succeed.c
-index 17cdc6e..c046c1d 100644
---- a/backends/test/pk-backend-test-succeed.c
-+++ b/backends/test/pk-backend-test-succeed.c
-@@ -236,7 +236,7 @@ backend_search_name_timeout (gpointer data)
- static void
- backend_search_name (PkBackend *backend, PkFilterEnum filters, const gchar *search)
- {
--      pk_backend_no_percentage_updates (backend);
-+      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
-       g_timeout_add (200000, backend_search_name_timeout, backend);
- }
-diff --git a/backends/yum/helpers/yumBackend.py b/backends/yum/helpers/yumBackend.py
-index f76e27c..5b2da8f 100644
---- a/backends/yum/helpers/yumBackend.py
-+++ b/backends/yum/helpers/yumBackend.py
-@@ -801,6 +801,8 @@ class PackageKitYumBackend(PackageKitBaseBackend):
-         old_throttle = self.yumbase.conf.throttle
-         self.yumbase.conf.throttle = "60%" # Set bandwidth throttle to 60%
-                                            # to avoid taking all the system's bandwidth.
-+        old_skip_broken = self.yumbase.conf.skip_broken
-+        self.yumbase.conf.skip_broken = 1
-         try:
-             txmbr = self.yumbase.update() # Add all updates to Transaction
-@@ -812,6 +814,7 @@ class PackageKitYumBackend(PackageKitBaseBackend):
-             self.error(ERROR_NO_PACKAGES_TO_UPDATE,"Nothing to do")
-         self.yumbase.conf.throttle = old_throttle
-+        self.yumbase.conf.skip_broken = old_skip_broken
-     def refresh_cache(self):
-         '''
-@@ -905,7 +908,7 @@ class PackageKitYumBackend(PackageKitBaseBackend):
-         if txmbrs:
-             self._runYumTransaction()
-         else:
--            self.error(ERROR_PACKAGE_ALREADY_INSTALLED,"This package could not be installed as it is already installed")
-+            self.error(ERROR_PACKAGE_ALREADY_INSTALLED,"The package is already installed")
-     def _checkForNewer(self,po):
-         pkgs = self.yumbase.pkgSack.returnNewestByName(name=po.name)
-@@ -1003,7 +1006,7 @@ class PackageKitYumBackend(PackageKitBaseBackend):
-             return False
-         if self._is_inst(po):
--            self.error(ERROR_PACKAGE_ALREADY_INSTALLED, "%s is already installed" % str(po))
-+            self.error(ERROR_PACKAGE_ALREADY_INSTALLED, "The package %s is already installed" % str(po))
-             return False
-         if len(self.yumbase.conf.exclude) > 0:
-diff --git a/backends/yum2/helpers/testyum2.py b/backends/yum2/helpers/testyum2.py
-index cdec507..85b47f9 100755
---- a/backends/yum2/helpers/testyum2.py
-+++ b/backends/yum2/helpers/testyum2.py
-@@ -80,7 +80,7 @@ try:
-         #iface.GetPackages(FILTER_INSTALLED,'no')
-     if cmd == 'get-repolist' or cmd == 'all':
-         print "Testing GetRepoList()"
--        iface.GetRepoList()
-+        iface.GetRepoList("")
-     if cmd == 'get-updatedetail' or cmd == 'all':
-         print "Testing GetUpdateDetail(PKG_ID)"
-         iface.GetUpdateDetail(PKG_ID)
-diff --git a/backends/yum2/helpers/yumDBUSBackend.py b/backends/yum2/helpers/yumDBUSBackend.py
-index 9cfed94..29f5b03 100755
---- a/backends/yum2/helpers/yumDBUSBackend.py
-+++ b/backends/yum2/helpers/yumDBUSBackend.py
-@@ -434,7 +434,7 @@ class PackageKitYumBackend(PackageKitBaseBackend):
-         try:
-             pkgGroupDict = self._buildGroupDict()
-             fltlist = filters.split(';')
--            found = {}
-+            installed_nevra = [] # yum returns packages as available even when installed
-             if not FILTER_NOT_INSTALLED in fltlist:
-                 # Check installed for group
-@@ -450,21 +450,31 @@ class PackageKitYumBackend(PackageKitBaseBackend):
-                             group = groupMap[cg]           # use the pk group name, instead of yum 'category/group'
-                     if group == key:
-                         if self._do_extra_filtering(pkg, fltlist):
--                            self._show_package(pkg, INFO_INSTALLED)
-+                            package_list.append((pkg,INFO_INSTALLED))
-+                    installed_nevra.append(self._get_nevra(pkg))                        
-+
-             if not FILTER_INSTALLED in fltlist:
-                 # Check available for group
-                 for pkg in self.yumbase.pkgSack:
-                     if self._cancel_check("Search cancelled."):
-                         # _cancel_check() sets the error message, unlocks yum, and calls Finished()
-                         return
--                    group = GROUP_OTHER
--                    if pkgGroupDict.has_key(pkg.name):
--                        cg = pkgGroupDict[pkg.name]
--                        if groupMap.has_key(cg):
--                            group = groupMap[cg]
--                    if group == key:
--                        if self._do_extra_filtering(pkg, fltlist):
--                            self._show_package(pkg, INFO_AVAILABLE)
-+
-+                    nevra = self._get_nevra(pkg)
-+                    if nevra not in installed_nevra:
-+                        group = GROUP_OTHER
-+                        if pkgGroupDict.has_key(pkg.name):
-+                            cg = pkgGroupDict[pkg.name]
-+                            if groupMap.has_key(cg):
-+                                group = groupMap[cg]
-+                        if group == key:
-+                            if self._do_extra_filtering(pkg, fltlist):
-+                                package_list.append((pkg,INFO_AVAILABLE))
-+
-+        except yum.Errors.GroupsError,e:
-+            self._unlock_yum()
-+            self.ErrorCode(ERROR_GROUP_NOT_FOUND, str(e))
-+            self.Finished(EXIT_FAILED)
-         except yum.Errors.RepoError,e:
-             self.Message(MESSAGE_NOTICE, "The package cache is invalid and is being rebuilt.")
-             self._refresh_yum_cache()
-@@ -473,6 +483,14 @@ class PackageKitYumBackend(PackageKitBaseBackend):
-             return
-+        # basename filter if specified
-+        if FILTER_BASENAME in fltlist:
-+            for (pkg,status) in self._basename_filter(package_list):
-+                self._show_package(pkg,status)
-+        else:
-+            for (pkg,status) in package_list:
-+                self._show_package(pkg,status)
-+
-         self._unlock_yum()
-         self.Finished(EXIT_SUCCESS)
-@@ -724,6 +742,11 @@ class PackageKitYumBackend(PackageKitBaseBackend):
-             #we might have a rounding error
-             self.PercentageChanged(100)
-+        except yum.Errors.RepoError,e:
-+            self._unlock_yum()
-+            self.ErrorCode(ERROR_REPO_CONFIGURATION_ERROR,str(e))
-+            self.Finished(EXIT_FAILED)
-+            self.Exit()
-         except yum.Errors.YumBaseError, e:
-             self._unlock_yum()
-             # This should be a better-defined error, but I'm not sure
-@@ -837,6 +860,7 @@ class PackageKitYumBackend(PackageKitBaseBackend):
-         Needed to be implemented in a sub class
-         '''
-         if inst_file.endswith('.src.rpm'):
-+            self._unlock_yum()
-             self.ErrorCode(ERROR_CANNOT_INSTALL_SOURCE_PACKAGE,'Backend will not install a src rpm file')
-             self.Finished(EXIT_FAILED)
-             return
-@@ -1385,30 +1409,30 @@ class PackageKitYumBackend(PackageKitBaseBackend):
-             res = self.yumbase.searchGenerator(searchlist, [key])
-             fltlist = filters.split(';')
--            available = []
--            count = 1
-+            seen_nevra = [] # yum returns packages as available even when installed
-+            pkg_list = [] # only do the second iteration on not installed pkgs
-+            package_list = [] #we can't do emitting as found if we are post-processing
-+
-             for (pkg,values) in res:
-                 if self._cancel_check("Search cancelled."):
-                     return False
-                 # are we installed?
-                 if pkg.repo.id == 'installed':
--                    if FILTER_NOT_INSTALLED not in fltlist:
--                        if self._do_extra_filtering(pkg,fltlist):
--                            count+=1
--                            if count > 100:
--                                break
--                            self._show_package(pkg, INFO_INSTALLED)
-+                    if self._do_extra_filtering(pkg,fltlist):
-+                        package_list.append((pkg,INFO_INSTALLED))
-+                        seen_nevra.append(self._get_nevra(pkg))
-                 else:
--                    available.append(pkg)
-+                    pkg_list.append(pkg)
--            # Now show available packages.
--            if FILTER_INSTALLED not in fltlist:
--                for pkg in available:
--                    if self._cancel_check("Search cancelled."):
--                        return False
--                    if self._do_extra_filtering(pkg,fltlist):
--                        self._show_package(pkg, INFO_AVAILABLE)
-+            for pkg in pkg_list:
-+                if self._cancel_check("Search cancelled."):
-+                    return False
-+                nevra = self._get_nevra(pkg)
-+                if nevra not in seen_nevra:
-+                    if self._do_extra_filtering(pkg,fltlist):
-+                        package_list.append((pkg,INFO_AVAILABLE))
-+                        seen_nevra.append(self._get_nevra(pkg))
-         except yum.Errors.RepoError,e:
-             self.Message(MESSAGE_NOTICE, "The package cache is invalid and is being rebuilt.")
-             self._refresh_yum_cache()
-@@ -1417,13 +1441,22 @@ class PackageKitYumBackend(PackageKitBaseBackend):
-             return False
-+        # basename filter if specified
-+        if FILTER_BASENAME in fltlist:
-+            for (pkg,status) in self._basename_filter(package_list):
-+                self._show_package(pkg,status)
-+        else:
-+            for (pkg,status) in package_list:
-+                self._show_package(pkg,status)
-+
-         return True
-     def _do_extra_filtering(self,pkg,filterList):
-         ''' do extra filtering (gui,devel etc) '''
-         for filter in filterList:
-             if filter in (FILTER_INSTALLED, FILTER_NOT_INSTALLED):
--                continue
-+                if not self._do_installed_filtering(filter,pkg):
-+                    return False
-             elif filter in (FILTER_GUI, FILTER_NOT_GUI):
-                 if not self._do_gui_filtering(filter, pkg):
-                     return False
-@@ -1433,11 +1466,17 @@ class PackageKitYumBackend(PackageKitBaseBackend):
-             elif filter in (FILTER_FREE, FILTER_NOT_FREE):
-                 if not self._do_free_filtering(filter, pkg):
-                     return False
--            elif filter in (FILTER_BASENAME, FILTER_NOT_BASENAME):
--                if not self._do_basename_filtering(filter, pkg):
--                    return False
-         return True
-+    def _do_installed_filtering(self,flt,pkg):
-+        isInstalled = False
-+        if flt == FILTER_INSTALLED:
-+            wantInstalled = True
-+        else:
-+            wantInstalled = False
-+        isInstalled = pkg.repo.id == 'installed'
-+        return isInstalled == wantInstalled
-+
-     def _do_gui_filtering(self,flt,pkg):
-         isGUI = False
-         if flt == FILTER_GUI:
-@@ -1477,32 +1516,7 @@ class PackageKitYumBackend(PackageKitBaseBackend):
-         return isFree == wantFree
--    def _do_basename_filtering(self,flt,pkg):
--        if flt == FILTER_BASENAME:
--            wantBase = True
--        else:
--            wantBase = False
--
--        isBase = self._check_basename(pkg)
--
--        return isBase == wantBase
--    def _check_basename(self, pkg):
--        '''
--        If a package does not have a source rpm (If that ever
--        happens), or it does have a source RPM, and the package's name
--        is the same as the source RPM's name, then we assume it is the
--        'base' package.
--        '''
--        basename = pkg.name
--
--        if pkg.sourcerpm:
--            basename = rpmUtils.miscutils.splitFilename(pkg.sourcerpm)[0]
--
--        if basename == pkg.name:
--            return True
--
--        return False
-     def _is_development_repo(self, repo):
-         if repo.endswith('-debuginfo'):
-@@ -1576,28 +1590,41 @@ class PackageKitYumBackend(PackageKitBaseBackend):
-         '''
-         find a package based on a package id (name;version;arch;repoid)
-         '''
--        # Split up the id
--        (n,idver,a,d) = self.get_package_from_id(id)
--        # get e,v,r from package id version
--        e,v,r = self._getEVR(idver)
-+        # is this an real id or just an name
-+        if len(id.split(';')) > 1:
-+            # Split up the id
-+            (n,idver,a,d) = self.get_package_from_id(id)
-+            # get e,v,r from package id version
-+            e,v,r = self._getEVR(idver)
-+        else:
-+            n = id
-+            e = v = r = a = None
-         # search the rpmdb for the nevra
-         pkgs = self.yumbase.rpmdb.searchNevra(name=n,epoch=e,ver=v,rel=r,arch=a)
--        # if the package is found, then return it
-+        # if the package is found, then return it (do not have to match the repo_id)
-         if len(pkgs) != 0:
-             return pkgs[0],True
-         # search the pkgSack for the nevra
--        pkgs = self.yumbase.pkgSack.searchNevra(name=n,epoch=e,ver=v,rel=r,arch=a)
--        # if the package is found, then return it
--        if len(pkgs) != 0:
--            return pkgs[0],False
--        else:
-+        try:
-+            pkgs = self.yumbase.pkgSack.searchNevra(name=n,epoch=e,ver=v,rel=r,arch=a)
-+        except yum.Errors.RepoError,e:
-+            self.error(ERROR_REPO_NOT_AVAILABLE,str(e))
-+        # nothing found
-+        if len(pkgs) == 0:
-             return None,False
-+        # one NEVRA in a single repo
-+        if len(pkgs) == 1:
-+            return pkgs[0],False
-+        # we might have the same NEVRA in multiple repos, match by repo name
-+        for pkg in pkgs:
-+            if d == pkg.repoid:
-+                return pkg,False
-+        # repo id did not match
-+        return None,False
-     def _is_inst(self,pkg):
-         return self.yumbase.rpmdb.installed(po=pkg)
--
--
-     def _installable(self, pkg, ematch=False):
-         """check if the package is reasonably installable, true/false"""
-@@ -1764,6 +1791,57 @@ class PackageKitYumBackend(PackageKitBaseBackend):
-             return INFO_ENHANCEMENT
-         else:
-             return INFO_UNKNOWN
-+    def _is_main_package(self,repo):
-+        if repo.endswith('-debuginfo'):
-+            return False
-+        if repo.endswith('-devel'):
-+            return False
-+        if repo.endswith('-libs'):
-+            return False
-+        return True
-+
-+    def _basename_filter(self,package_list):
-+        '''
-+        Filter the list so that the number of packages are reduced.
-+        This is done by only displaying gtk2 rather than gtk2-devel, gtk2-debuginfo, etc.
-+        This imlementation is done by comparing the SRPM name, and if not falling back
-+        to the first entry.
-+        We have to fall back else we don't emit packages where the SRPM does not produce a
-+        RPM with the same name, for instance, mono produces mono-core, mono-data and mono-winforms.
-+        @package_list: a (pkg,status) list of packages
-+        A new list is returned that has been filtered
-+        '''
-+        base_list = []
-+        output_list = []
-+        base_list_already_got = []
-+
-+        #find out the srpm name and add to a new array of compound data
-+        for (pkg,status) in package_list:
-+            if pkg.sourcerpm:
-+                base = rpmUtils.miscutils.splitFilename(pkg.sourcerpm)[0]
-+                base_list.append ((pkg,status,base,pkg.version));
-+            else:
-+                base_list.append ((pkg,status,'nosrpm',pkg.version));
-+
-+        #find all the packages that match thier basename name (done seporately so we get the "best" match)
-+        for (pkg,status,base,version) in base_list:
-+            if base == pkg.name and (base,version) not in base_list_already_got:
-+                output_list.append((pkg,status))
-+                base_list_already_got.append ((base,version))
-+
-+        #for all the ones not yet got, can we match against a non devel match?
-+        for (pkg,status,base,version) in base_list:
-+            if (base,version) not in base_list_already_got:
-+                if self._is_main_package(pkg.name):
-+                    output_list.append((pkg,status))
-+                    base_list_already_got.append ((base,version))
-+
-+        #add the remainder of the packages, which should just be the single debuginfo's
-+        for (pkg,status,base,version) in base_list:
-+            if (base,version) not in base_list_already_got:
-+                output_list.append((pkg,status))
-+                base_list_already_got.append ((base,version))
-+        return output_list
-     def _get_obsoleted(self,name):
-         obsoletes = self.yumbase.up.getObsoletesTuples( newest=1 )
-diff --git a/backends/zypp/pk-backend-zypp.cpp b/backends/zypp/pk-backend-zypp.cpp
-index 746da82..15c4b4f 100644
---- a/backends/zypp/pk-backend-zypp.cpp
-+++ b/backends/zypp/pk-backend-zypp.cpp
-@@ -1170,7 +1170,7 @@ backend_find_packages_thread (PkBackend *backend)
-       mode = pk_backend_get_uint (backend, "mode");
-       pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
--      pk_backend_no_percentage_updates (backend);
-+      pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
-       std::vector<zypp::sat::Solvable> *v = new std::vector<zypp::sat::Solvable>;
-       std::vector<zypp::sat::Solvable> *v2 = new std::vector<zypp::sat::Solvable>;
-diff --git a/client/pk-console.c b/client/pk-console.c
-index 8f69068..5a05a8e 100644
---- a/client/pk-console.c
-+++ b/client/pk-console.c
-@@ -50,7 +50,7 @@ static gboolean awaiting_space = FALSE;
- static gboolean trusted = TRUE;
- static guint timer_id = 0;
- static guint percentage_last = 0;
--static gchar *filename = NULL;
-+static gchar **files_cache = NULL;
- static PkControl *control = NULL;
- static PkClient *client = NULL;
- static PkClient *client_task = NULL;
-@@ -494,6 +494,12 @@ pk_console_perhaps_resolve (PkClient *client, PkFilterEnum filter, const gchar *
-               return g_strdup (package);
-       }
-+      ret = pk_client_reset (client_task, error);
-+      if (ret == FALSE) {
-+              pk_warning ("failed to reset client task");
-+              return NULL;
-+      }
-+
-       /* we need to resolve it */
-       ret = pk_client_resolve (client_task, filter, package, error);
-       if (ret == FALSE) {
-@@ -549,20 +555,93 @@ pk_console_perhaps_resolve (PkClient *client, PkFilterEnum filter, const gchar *
- }
- /**
-- * pk_console_install_package:
-+ * pk_console_install_stuff:
-  **/
- static gboolean
--pk_console_install_package (PkClient *client, const gchar *package, GError **error)
-+pk_console_install_stuff (PkClient *client, gchar **packages, GError **error)
- {
--      gboolean ret;
--      gchar *package_id;
--      package_id = pk_console_perhaps_resolve (client, PK_FILTER_ENUM_NOT_INSTALLED, package, error);
--      if (package_id == NULL) {
--              g_print ("%s\n", _("Could not find a package with that name to install, or package already installed"));
--              return FALSE;
-+      gboolean ret = TRUE;
-+      gboolean is_local;
-+      gchar *package_id = NULL;
-+      gchar **package_ids = NULL;
-+      gchar **files = NULL;
-+      guint i;
-+      guint length;
-+      GPtrArray *array_packages;
-+      GPtrArray *array_files;
-+
-+      array_packages = g_ptr_array_new ();
-+      array_files = g_ptr_array_new ();
-+      length = g_strv_length (packages);
-+      for (i=2; i<length; i++) {
-+              is_local = g_file_test (packages[i], G_FILE_TEST_EXISTS);
-+              if (is_local) {
-+                      g_ptr_array_add (array_files, g_strdup (packages[i]));
-+              } else {
-+                      package_id = pk_console_perhaps_resolve (client, PK_FILTER_ENUM_NOT_INSTALLED, packages[i], error);
-+                      if (package_id == NULL) {
-+                              g_print ("%s\n", _("Could not find a package with that name to install, or package already installed"));
-+                              ret = FALSE;
-+                              break;
-+                      }
-+                      g_ptr_array_add (array_packages, package_id);
-+              }
-       }
--      ret = pk_client_install_package (client, package_id, error);
--      g_free (package_id);
-+
-+      /* one of the resolves failed */
-+      if (!ret) {
-+              pk_warning ("resolve failed");
-+              goto out;
-+      }
-+
-+
-+      /* any to process? */
-+      if (array_packages->len > 0) {
-+              /* convert to strv */
-+              package_ids = pk_ptr_array_to_argv (array_packages);
-+
-+              /* reset */
-+              ret = pk_client_reset (client, error);
-+              if (!ret) {
-+                      pk_warning ("failed to reset");
-+                      goto out;
-+              }
-+
-+              ret = pk_client_install_package (client, package_id, error);
-+              if (!ret) {
-+                      pk_warning ("failed to install packages");
-+                      goto out;
-+              }
-+      }
-+
-+      /* any to process? */
-+      if (array_files->len > 0) {
-+              /* convert to strv */
-+              files = pk_ptr_array_to_argv (array_files);
-+
-+              /* save for untrusted callback */
-+              g_strfreev (files_cache);
-+              files_cache = g_strdupv (files);
-+
-+              /* reset */
-+              ret = pk_client_reset (client, error);
-+              if (!ret) {
-+                      pk_warning ("failed to reset");
-+                      goto out;
-+              }
-+
-+              ret = pk_client_install_files (client, trusted, files, error);
-+              if (!ret) {
-+                      pk_warning ("failed to install files");
-+                      goto out;
-+              }
-+      }
-+
-+out:
-+      g_strfreev (package_ids);
-+      g_strfreev (files);
-+      g_ptr_array_free (array_files, TRUE);
-+      g_ptr_array_free (array_packages, TRUE);
-       return ret;
- }
-@@ -570,16 +649,16 @@ pk_console_install_package (PkClient *client, const gchar *package, GError **err
-  * pk_console_remove_only:
-  **/
- static gboolean
--pk_console_remove_only (PkClient *client, const gchar *package_id, gboolean force, gboolean autoremove, GError **error)
-+pk_console_remove_only (PkClient *client, gchar **package_ids, gboolean force, GError **error)
- {
-       gboolean ret;
--      pk_debug ("remove %s", package_id);
-+      pk_debug ("remove+ %s", package_ids[0]);
-       ret = pk_client_reset (client, error);
-       if (!ret) {
-               return ret;
-       }
--      return pk_client_remove_package (client, package_id, force, autoremove, error);
-+      return pk_client_remove_packages (client, package_ids, force, FALSE, error);
- }
- /**
-@@ -625,64 +704,99 @@ pk_console_get_prompt (const gchar *question, gboolean defaultyes)
- }
- /**
-- * pk_console_remove_package:
-+ * pk_console_remove_packages:
-  **/
- static gboolean
--pk_console_remove_package (PkClient *client, const gchar *package, GError **error)
-+pk_console_remove_packages (PkClient *client, gchar **packages, GError **error)
- {
-       gchar *package_id;
--      gboolean ret;
--      guint length;
-+      gboolean ret = TRUE;
-       PkPackageItem *item;
-       PkPackageId *ident;
--      guint i;
-+      guint i, j;
-+      guint size;
-+      guint length;
-       gboolean remove;
-+      GPtrArray *array;
-+      gchar **package_ids = NULL;
-+      PkPackageList *list;
-+
-+      array = g_ptr_array_new ();
-+      list = pk_package_list_new ();
-+      length = g_strv_length (packages);
-+      for (i=2; i<length; i++) {
-+              package_id = pk_console_perhaps_resolve (client, PK_FILTER_ENUM_INSTALLED, packages[i], error);
-+              if (package_id == NULL) {
-+                      g_print ("%s:%s\n", _("Could not find a package to remove"), packages[i]);
-+                      ret = FALSE;
-+                      break;
-+              }
-+              g_ptr_array_add (array, g_strdup (package_id));
-+              pk_debug ("resolved to %s", package_id);
-+              g_free (package_id);
-+      }
--      package_id = pk_console_perhaps_resolve (client, PK_FILTER_ENUM_INSTALLED, package, error);
--      if (package_id == NULL) {
--              g_print ("%s\n", _("Could not find a package with that name to remove"));
--              return FALSE;
-+      /* one of the resolves failed */
-+      if (!ret) {
-+              goto out;
-       }
-+      /* convert to strv */
-+      package_ids = pk_ptr_array_to_argv (array);
-+
-       /* are we dumb and can't check for requires? */
-       if (!pk_enums_contain (roles, PK_ROLE_ENUM_GET_REQUIRES)) {
-               /* no, just try to remove it without deps */
--              ret = pk_console_remove_only (client, package_id, FALSE, FALSE, error);
--              g_free (package_id);
--              return ret;
-+              ret = pk_console_remove_only (client, package_ids, FALSE, error);
-+              goto out;
-       }
--      /* see if any packages require this one */
--      ret = pk_client_reset (client_task, error);
--      if (!ret) {
--              pk_warning ("failed to reset");
--              return FALSE;
-+      /* get the requires packages for each package_id */
-+      length = g_strv_length (package_ids);
-+      for (i=0; i<length; i++) {
-+              ret = pk_client_reset (client_task, error);
-+              if (!ret) {
-+                      pk_warning ("failed to reset");
-+                      break;
-+              }
-+
-+              pk_debug ("Getting installed requires for %s", package_ids[i]);
-+              /* see if any packages require this one */
-+              ret = pk_client_get_requires (client_task, PK_FILTER_ENUM_INSTALLED, package_ids[i], TRUE, error);
-+              if (!ret) {
-+                      pk_warning ("failed to get requires");
-+                      break;
-+              }
-+
-+              /* see how many packages there are */
-+              size = pk_client_package_buffer_get_size (client_task);
-+              for (j=0; j<size; j++) {
-+                      item = pk_client_package_buffer_get_item (client_task, j);
-+                      pk_package_list_add_item (list, item);
-+              }
-       }
--      pk_debug ("Getting installed requires for %s", package_id);
--      ret = pk_client_get_requires (client_task, PK_FILTER_ENUM_INSTALLED, package_id, TRUE, error);
-+      /* one of the get-requires failed */
-       if (!ret) {
--              return FALSE;
-+              goto out;
-       }
--      /* see how many packages there are */
--      length = pk_client_package_buffer_get_size (client_task);
--
-       /* if there are no required packages, just do the remove */
-+      length = pk_package_list_get_size (list);
-       if (length == 0) {
-               pk_debug ("no requires");
--              ret = pk_console_remove_only (client, package_id, FALSE, FALSE, error);
--              g_free (package_id);
--              return ret;
-+              ret = pk_console_remove_only (client, package_ids, FALSE, error);
-+              goto out;
-       }
-+
-       /* present this to the user */
-       if (awaiting_space) {
-               g_print ("\n");
-       }
-       g_print ("%s:\n", _("The following packages have to be removed"));
-       for (i=0; i<length; i++) {
--              item = pk_client_package_buffer_get_item (client_task, i);
-+              item = pk_package_list_get_item (list, i);
-               ident = pk_package_id_new_from_string (item->package_id);
-               g_print ("%i\t%s-%s\n", i, ident->name, ident->version);
-               pk_package_id_free (ident);
-@@ -694,14 +808,17 @@ pk_console_remove_package (PkClient *client, const gchar *package, GError **erro
-       /* we chickened out */
-       if (remove == FALSE) {
-               g_print ("%s\n", _("Cancelled!"));
--              g_free (package_id);
--              return FALSE;
-+              ret = FALSE;
-+              goto out;
-       }
-       /* remove all the stuff */
--      ret = pk_console_remove_only (client, package_id, TRUE, FALSE, error);
--      g_free (package_id);
-+      ret = pk_console_remove_only (client, package_ids, TRUE, error);
-+out:
-+      g_object_unref (list);
-+      g_strfreev (package_ids);
-+      g_ptr_array_free (array, TRUE);
-       return ret;
- }
-@@ -840,7 +957,7 @@ pk_console_error_code_cb (PkClient *client, PkErrorCodeEnum error_code, const gc
-           error_code == PK_ERROR_ENUM_MISSING_GPG_SIGNATURE && trusted) {
-               pk_debug ("need to try again with trusted FALSE");
-               trusted = FALSE;
--              ret = pk_client_install_file (client_install_files, trusted, filename, &error);
-+              ret = pk_client_install_files (client_install_files, trusted, files_cache, &error);
-               /* we succeeded, so wait for the requeue */
-               if (!ret) {
-                       pk_warning ("failed to install file second time: %s", error->message);
-@@ -1153,7 +1270,6 @@ main (int argc, char *argv[])
-       const gchar *value = NULL;
-       const gchar *details = NULL;
-       const gchar *parameter = NULL;
--      PkRoleEnum roles;
-       PkGroupEnum groups;
-       gchar *text;
-       ret = FALSE;
-@@ -1324,15 +1440,7 @@ main (int argc, char *argv[])
-                       g_print (_("You need to specify a package or file to install"));
-                       goto out;
-               }
--              /* is it a local file? */
--              ret = g_file_test (value, G_FILE_TEST_EXISTS);
--              if (ret) {
--                      ret = pk_client_install_file (client, trusted, value, &error);
--                      /* we need this for the untrusted try */
--                      filename = g_strdup (value);
--              } else {
--                      ret = pk_console_install_package (client, value, &error);
--              }
-+              ret = pk_console_install_stuff (client, argv, &error);
-       } else if (strcmp (mode, "install-sig") == 0) {
-               if (value == NULL || details == NULL || parameter == NULL) {
-@@ -1346,7 +1454,7 @@ main (int argc, char *argv[])
-                       g_print (_("You need to specify a package to remove"));
-                       goto out;
-               }
--              ret = pk_console_remove_package (client, value, &error);
-+              ret = pk_console_remove_packages (client, argv, &error);
-       } else if (strcmp (mode, "accept-eula") == 0) {
-               if (value == NULL) {
-@@ -1465,9 +1573,9 @@ main (int argc, char *argv[])
-               ret = pk_client_get_packages (client, filters, &error);
-       } else if (strcmp (mode, "get-actions") == 0) {
--              roles = pk_control_get_actions (control);
-               text = pk_role_enums_to_text (roles);
--              g_print ("roles=%s\n", text);
-+              g_strdelimit (text, ";", '\n');
-+              g_print ("%s\n", text);
-               g_free (text);
-               maybe_sync = FALSE;
-               /* these can never fail */
-@@ -1476,7 +1584,8 @@ main (int argc, char *argv[])
-       } else if (strcmp (mode, "get-filters") == 0) {
-               filters = pk_control_get_filters (control);
-               text = pk_filter_enums_to_text (filters);
--              g_print ("filters=%s\n", text);
-+              g_strdelimit (text, ";", '\n');
-+              g_print ("%s\n", text);
-               g_free (text);
-               maybe_sync = FALSE;
-               /* these can never fail */
-@@ -1485,7 +1594,8 @@ main (int argc, char *argv[])
-       } else if (strcmp (mode, "get-groups") == 0) {
-               groups = pk_control_get_groups (control);
-               text = pk_group_enums_to_text (groups);
--              g_print ("groups=%s\n", text);
-+              g_strdelimit (text, ";", '\n');
-+              g_print ("%s\n", text);
-               g_free (text);
-               maybe_sync = FALSE;
-               /* these can never fail */
-@@ -1525,7 +1635,7 @@ out:
-       g_free (options_help);
-       g_free (filter);
-       g_free (summary);
--      g_free (filename);
-+      g_strfreev (files_cache);
-       g_object_unref (control);
-       g_object_unref (client);
-       g_object_unref (client_task);
-diff --git a/configure.ac b/configure.ac
-index 9d734e1..f614d2b 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -535,7 +535,7 @@ if test x$enable_box = xyes; then
- fi
- if test x$enable_opkg = xyes; then
--      PKG_CHECK_MODULES(OPKG, libopkg = 0.1.3)
-+      PKG_CHECK_MODULES(OPKG, libopkg = 0.1.4)
-       AC_SUBST(OPKG_CFLAGS)
-       AC_SUBST(OPKG_LIBS)
- fi
-diff --git a/contrib/yum-packagekit/refresh-packagekit.py b/contrib/yum-packagekit/refresh-packagekit.py
-index 9c0bdf4..b440539 100644
---- a/contrib/yum-packagekit/refresh-packagekit.py
-+++ b/contrib/yum-packagekit/refresh-packagekit.py
-@@ -35,7 +35,7 @@ def posttrans_hook(conduit):
-                                           '/org/freedesktop/PackageKit')
-         packagekit_iface = dbus.Interface(packagekit_proxy, 'org.freedesktop.PackageKit')
-         packagekit_iface.StateHasChanged('posttrans')
--    except dbus.DBusException, e:
-+    except Exception, e:
-         conduit.info(2, "Unable to send message to PackageKit")
-         conduit.info(6, "%s" %(e,))
-diff --git a/data/tests/Makefile.am b/data/tests/Makefile.am
-index d15dd6c..6935e66 100644
---- a/data/tests/Makefile.am
-+++ b/data/tests/Makefile.am
-@@ -5,6 +5,7 @@ NULL =
- TEST_FILES =                                          \
-       pk-spawn-test.sh                                \
-+      pk-spawn-proxy.sh                               \
-       pk-spawn-test-sigquit.sh                        \
-       pk-spawn-test-profiling.sh                      \
-       $(NULL)
-diff --git a/data/tests/pk-spawn-proxy.sh b/data/tests/pk-spawn-proxy.sh
-new file mode 100755
-index 0000000..57774f1
---- /dev/null
-+++ b/data/tests/pk-spawn-proxy.sh
-@@ -0,0 +1,20 @@
-+#!/bin/bash
-+# Copyright (C) 2008 Richard Hughes <richard@hughsie.com>
-+# Licensed under the GNU General Public License Version 2
-+# 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 2 of the License, or
-+# (at your option) any later version.
-+
-+if [ -z "${http_proxy}" ]; then
-+      echo "no http proxy"
-+      exit 1
-+fi
-+
-+if [ -z "${ftp_proxy}" ]; then
-+      echo "no ftp proxy"
-+      exit 1
-+fi
-+
-+echo -e "percentage\t100"
-+
-diff --git a/docs/html/index.html b/docs/html/index.html
-index 7270eb7..d60f825 100644
---- a/docs/html/index.html
-+++ b/docs/html/index.html
-@@ -9,9 +9,9 @@
- <table align="center" class="title">
- <tr>
-- <td><img src="img/packagekit.png" alt="[img]"/></td>
-+ <td><img src="img/packagekit.png" alt=""/></td>
-  <td width="95%" valign="middle"><p class="title">PackageKit Main Page</p></td>
-- <td><img src="img/packagekit.png" alt="[img]"/></td>
-+ <td><img src="img/packagekit.png" alt=""/></td>
- </tr>
- </table>
-@@ -20,10 +20,10 @@
- <table align="center" cellpadding="5px" border="0">
- <tr>
-- <td align="center"><a href="pk-intro.html"><img src="img/large-accessories-text-editor.png" width="128" alt="[img]"/></a></td>
-- <td align="center"><a href="pk-using.html"><img src="img/large-preferences-system.png" width="128" alt="[img]"/></a></td>
-- <td align="center"><a href="pk-download.html"><img src="img/large-dialog-information.png" width="128" alt="[img]"/></a></td>
-- <td align="center"><a href="pk-screenshots.html"><img src="img/large-emblem-photos.png" width="128" alt="[img]"/></a></td>
-+ <td align="center"><a href="pk-intro.html"><img src="img/large-accessories-text-editor.png" width="128" alt=""/></a></td>
-+ <td align="center"><a href="pk-using.html"><img src="img/large-preferences-system.png" width="128" alt=""/></a></td>
-+ <td align="center"><a href="pk-download.html"><img src="img/large-dialog-information.png" width="128" alt=""/></a></td>
-+ <td align="center"><a href="pk-screenshots.html"><img src="img/large-emblem-photos.png" width="128" alt=""/></a></td>
- </tr>
- <tr>
-  <td><p class="indextitle"><a href="pk-intro.html" class="indextitle">What is<br/>PackageKit?</a></p></td>
-@@ -32,10 +32,10 @@
-  <td><p class="indextitle"><a href="pk-screenshots.html" class="indextitle">Screenshots</a></p></td>
- </tr>
- <tr>
-- <td align="center"><a href="pk-authors.html"><img src="img/large-authors.png" width="128" alt="[img]"/></a></td>
-- <td align="center"><a href="pk-bugs.html"><img src="img/large-applications-development.png" width="128" alt="[img]"/></a></td>
-- <td align="center"><a href="pk-help.html"><img src="img/large-system-users.png" width="128" alt="[img]"/></a></td>
-- <td align="center"><a href="pk-faq.html"><img src="img/large-help-browser.png" width="128" alt="[img]"/></a></td>
-+ <td align="center"><a href="pk-authors.html"><img src="img/large-authors.png" width="128" alt=""/></a></td>
-+ <td align="center"><a href="pk-bugs.html"><img src="img/large-applications-development.png" width="128" alt=""/></a></td>
-+ <td align="center"><a href="pk-help.html"><img src="img/large-system-users.png" width="128" alt=""/></a></td>
-+ <td align="center"><a href="pk-faq.html"><img src="img/large-help-browser.png" width="128" alt=""/></a></td>
- </tr>
- <tr>
-  <td><p class="indextitle"><a href="pk-authors.html" class="indextitle">Who develops<br/>PackageKit?</a></p></td>
-diff --git a/docs/html/pk-authors.html b/docs/html/pk-authors.html
-index 08289ad..607a7a4 100644
---- a/docs/html/pk-authors.html
-+++ b/docs/html/pk-authors.html
-@@ -9,9 +9,9 @@
- <table align="center" class="title">
- <tr>
-- <td><img src="img/packagekit.png" alt="[img]"/></td>
-+ <td><img src="img/packagekit.png" alt=""/></td>
-  <td width="95%" valign="middle"><p class="title">Who develops PackageKit?</p></td>
-- <td><img src="img/packagekit.png" alt="[img]"/></td>
-+ <td><img src="img/packagekit.png" alt=""/></td>
- </tr>
- </table>
-@@ -22,7 +22,7 @@
- <table cellpadding="10">
- <tr>
-  <td>
--  <img src="img/author-hughsie.png" alt="[img]"/><!-- image should be 120px wide -->
-+  <img src="img/author-hughsie.png" alt=""/><!-- image should be 120px wide -->
-  </td>
-  <td>
-   <h2>Richard Hughes</h2>
-@@ -48,7 +48,7 @@
- <tr>
-  <td>
--  <img src="img/author-kenvandine.png" alt="[img]"/><!-- image should be 120px wide -->
-+  <img src="img/author-kenvandine.png" alt=""/><!-- image should be 120px wide -->
-  </td>
-  <td>
-   <h2>Ken VanDine</h2>
-@@ -66,7 +66,7 @@
- <tr>
-  <td>
--  <img src="img/author-btimothy.png" alt="[img]"/><!-- image should be 120px wide -->
-+  <img src="img/author-btimothy.png" alt=""/><!-- image should be 120px wide -->
-  </td>
-  <td>
-   <h2>Boyd Timothy</h2>
-@@ -84,7 +84,7 @@
- <tr>
-  <td>
--  <img src="img/author-rnorwood.png" alt="[img]"/><!-- image should be 120px wide -->
-+  <img src="img/author-rnorwood.png" alt=""/><!-- image should be 120px wide -->
-  </td>
-  <td>
-   <h2>Robin Norwood</h2>
-@@ -101,7 +101,7 @@
- <tr>
-  <td>
--  <img src="img/author-tomparker.png" alt="[img]"/><!-- image should be 120px wide -->
-+  <img src="img/author-tomparker.png" alt=""/><!-- image should be 120px wide -->
-  </td>
-  <td>
-   <h2>Tom Parker</h2>
-@@ -118,7 +118,7 @@
- <tr>
-  <td>
--  <img src="img/author-timlau.png" alt="[img]"/><!-- image should be 120px wide -->
-+  <img src="img/author-timlau.png" alt=""/><!-- image should be 120px wide -->
-  </td>
-  <td>
-   <h2>Tim Lauridsen</h2>
-@@ -139,7 +139,7 @@
- <tr>
-  <td>
--  <img src="img/author-lmacken.png" alt="[img]"/>
-+  <img src="img/author-lmacken.png" alt=""/>
-  </td>
-  <td>
-   <h2>Luke Macken</h2>
-@@ -154,7 +154,7 @@
- <tr>
-  <td>
--  <img src="img/author-grzegorzdabrowski.png" alt="[img]"/><!-- image should be 120px wide -->
-+  <img src="img/author-grzegorzdabrowski.png" alt=""/><!-- image should be 120px wide -->
-  </td>
-  <td>
-   <h2>Grzegorz Dąbrowski</h2>
-@@ -173,7 +173,7 @@
- <tr>
-  <td>
--  <img src="img/author-caglar.png" alt="[img]"/><!-- image should be 120px wide -->
-+  <img src="img/author-caglar.png" alt=""/><!-- image should be 120px wide -->
-  </td>
-  <td>
-   <h2>S.Çağlar Onur</h2>
-@@ -195,7 +195,7 @@
- <tr>
-  <td>
--  <img src="img/author-elliot.png" alt="[img]"/>
-+  <img src="img/author-elliot.png" alt=""/>
-  </td>
-  <td>
-   <h2>Elliot Peele</h2>
-@@ -210,7 +210,7 @@
- <tr>
-  <td>
--  <img src="img/author-jbowes.png" alt="[img]"/><!-- image should be 120px wide -->
-+  <img src="img/author-jbowes.png" alt=""/><!-- image should be 120px wide -->
-  </td>
-  <td>
-   <h2>James Bowes</h2>
-@@ -227,7 +227,7 @@
- <tr>
-  <td>
--  <img src="img/author-unknown.png" alt="[img]"/><!-- image should be 120px wide -->
-+  <img src="img/author-unknown.png" alt=""/><!-- image should be 120px wide -->
-  </td>
-  <td>
-   <h2>Thomas Wood</h2>
-@@ -247,7 +247,7 @@
- <tr>
-  <td>
--  <img src="img/author-unknown.png" alt="[img]"/><!-- image should be 120px wide -->
-+  <img src="img/author-unknown.png" alt=""/><!-- image should be 120px wide -->
-  </td>
-  <td>
-   <h2>Scott Reeves</h2>
-diff --git a/docs/html/pk-bugs.html b/docs/html/pk-bugs.html
-index 89f7c48..2ee12ea 100644
---- a/docs/html/pk-bugs.html
-+++ b/docs/html/pk-bugs.html
-@@ -9,9 +9,9 @@
- <table align="center" class="title">
- <tr>
-- <td><img src="img/packagekit.png" alt="[img]"/></td>
-+ <td><img src="img/packagekit.png" alt=""/></td>
-  <td width="95%" valign="middle"><p class="title">Reporting Bugs</p></td>
-- <td><img src="img/packagekit.png" alt="[img]"/></td>
-+ <td><img src="img/packagekit.png" alt=""/></td>
- </tr>
- </table>
-diff --git a/docs/html/pk-download.html b/docs/html/pk-download.html
-index 6f796b8..0cdc85c 100644
---- a/docs/html/pk-download.html
-+++ b/docs/html/pk-download.html
-@@ -9,9 +9,9 @@
- <table align="center" class="title">
- <tr>
-- <td><img src="img/packagekit.png" alt="[img]"/></td>
-+ <td><img src="img/packagekit.png" alt=""/></td>
-  <td width="95%" valign="middle"><p class="title">Where can I download it?</p></td>
-- <td><img src="img/packagekit.png" alt="[img]"/></td>
-+ <td><img src="img/packagekit.png" alt=""/></td>
- </tr>
- </table>
-diff --git a/docs/html/pk-faq.html b/docs/html/pk-faq.html
-index a25e2b7..efa8344 100644
---- a/docs/html/pk-faq.html
-+++ b/docs/html/pk-faq.html
-@@ -9,9 +9,9 @@
- <table align="center" class="title">
- <tr>
-- <td><center><img src="img/packagekit.png" alt="[img]"/></center></td>
-+ <td><center><img src="img/packagekit.png" alt=""/></center></td>
-  <td width="95%" valign="middle"><p class="title">Frequently Asked Questions</p></td>
-- <td><center><img src="img/packagekit.png" alt="[img]"/></center></td>
-+ <td><center><img src="img/packagekit.png" alt=""/></center></td>
- </tr>
- </table>
-@@ -22,6 +22,7 @@
- <h2>Table Of Contents</h2>
- <ul>
- <li><a href="#how-complete">How complete are the backends?</a></li>
-+<li><a href="#run-as-root">When run as root, gpk-application and pkcon do not work!</a></li>
- <li><a href="#session-system">Why is there a session service and and a system service?</a></li>
- <li><a href="#session-methods">How do I use PackageKit in my application?</a></li>
- <li><a href="#rawhide-updates">Why don't I get update details with Fedora Rawhide?</a></li>
-@@ -565,6 +566,19 @@
- </table>
- <hr>
-+<h3><a name="run-as-root">When run as root, <code>gpk-application</code> and <code>pkcon</code> do not work!</a></h3>
-+<p>
-+GTK+ tools should not be run as the root user, <b>PERIOD</b>.
-+Any GTK+ program run as the root user is a massive security hole -- GTK+ just isn't designed with
-+this in mind.
-+There are <b>numerous</b> attack vectors when running as root, and programs shouldn't do such
-+insane and insecure things.
-+</p>
-+<p>
-+Please see <a href="http://www.gtk.org/setuid.html">the GTK+ explanation</a> for more rationale.
-+</p>
-+
-+<hr>
- <h3><a name="session-system">Why is there a session service <b>and</b> and a system service?</a></h3>
- <p>
- PackageKit runs a process <code>packagekitd</code> that is a daemon that runs per-system.
-diff --git a/docs/html/pk-help.html b/docs/html/pk-help.html
-index 5b44d50..5bc7827 100644
---- a/docs/html/pk-help.html
-+++ b/docs/html/pk-help.html
-@@ -9,9 +9,9 @@
- <table align="center" class="title">
- <tr>
-- <td><img src="img/packagekit.png" alt="[img]"/></td>
-+ <td><img src="img/packagekit.png" alt=""/></td>
-  <td width="95%" valign="middle"><p class="title">How can I help?</p></td>
-- <td><img src="img/packagekit.png" alt="[img]"/></td>
-+ <td><img src="img/packagekit.png" alt=""/></td>
- </tr>
- </table>
-@@ -72,9 +72,9 @@ as for instructions!
- <b>0.2.2</b> - To be released June 2008
- </p>
- <ul>
--<li>Multiple package install and remove from pkcon <i>(0%)</i></li>
-+<li>Network proxy server support <i>(70%)</i></li>
-+<li>Multiple package install and remove from pkcon <i>(80%)</i></li>
- <li>NetworkManager integration so we can detect GPRS (and modem) connections. <i>(10%)</i></li>
--<li>Filter for source packages. <i>(0%)</i></li>
- </ul>
- <p>
- <b>0.2.3</b> - To be released July 2008
-@@ -84,6 +84,12 @@ as for instructions!
- <li>Multiple package installs from gpk-application <i>(0%)</i></li>
- <li>Ignoring packages from the update viewer per-session <i>(10%)</i></li>
- </ul>
-+<p>
-+<b>0.3.0</b> - To be released December 2008
-+</p>
-+<ul>
-+<li>More composite types <code>s</code> to <code>as</code> <i>(0%)</i></li>
-+</ul>
- <p>Back to the <a href="index.html">main page</a></p>
-diff --git a/docs/html/pk-intro.html b/docs/html/pk-intro.html
-index c42be21..64f72fc 100644
---- a/docs/html/pk-intro.html
-+++ b/docs/html/pk-intro.html
-@@ -9,9 +9,9 @@
- <table align="center" class="title">
- <tr>
-- <td><img src="img/packagekit.png" alt="[img]"/></td>
-+ <td><img src="img/packagekit.png" alt=""/></td>
-  <td width="95%" valign="middle"><p class="title">What is PackageKit?</p></td>
-- <td><img src="img/packagekit.png" alt="[img]"/></td>
-+ <td><img src="img/packagekit.png" alt=""/></td>
- </tr>
- </table>
-diff --git a/docs/html/pk-screenshots.html b/docs/html/pk-screenshots.html
-index 78bd01f..5c7d4fa 100644
---- a/docs/html/pk-screenshots.html
-+++ b/docs/html/pk-screenshots.html
-@@ -9,9 +9,9 @@
- <table align="center" class="title">
- <tr>
-- <td><center><img src="img/packagekit.png" alt="[img]"/></center></td>
-+ <td><center><img src="img/packagekit.png" alt=""/></center></td>
-  <td width="95%" valign="middle"><p class="title">Screenshots</p></td>
-- <td><center><img src="img/packagekit.png" alt="[img]"/></center></td>
-+ <td><center><img src="img/packagekit.png" alt=""/></center></td>
- </tr>
- </table>
-@@ -26,77 +26,77 @@
- <h1><a name="gnome">GNOME Screenshots</a></h1>
--<center><img src="img/gpk-application-search.png" alt="[img]"/></center>
-+<center><img src="img/gpk-application-search.png" alt=""/></center>
- <p class="caption">Add/Remove Software search</p>
--<center><img src="img/gpk-application-groups.png" alt="[img]"/></center>
-+<center><img src="img/gpk-application-groups.png" alt=""/></center>
- <p class="caption">Add/Remove Software groups</p>
--<center><img src="img/gpk-log.png" alt="[img]"/></center>
-+<center><img src="img/gpk-log.png" alt=""/></center>
- <p class="caption">Transaction viewer</p>
--<center><img src="img/gpk-updates-overview.png" alt="[img]"/></center>
-+<center><img src="img/gpk-updates-overview.png" alt=""/></center>
- <p class="caption">Update viewer overview</p>
--<center><img src="img/gpk-updates.png" alt="[img]"/></center>
-+<center><img src="img/gpk-updates.png" alt=""/></center>
- <p class="caption">Update viewer</p>
--<center><img src="img/gpk-prefs.png" alt="[img]"/></center>
-+<center><img src="img/gpk-prefs.png" alt=""/></center>
- <p class="caption">Auto update preferences</p>
--<center><img src="img/gpk-progress.png" alt="[img]"/></center>
-+<center><img src="img/gpk-progress.png" alt=""/></center>
- <p class="caption">Progress dialog</p>
--<center><img src="img/gpk-added-deps.png" alt="[img]"/></center>
-+<center><img src="img/gpk-added-deps.png" alt=""/></center>
- <p class="caption">Added check warning</p>
--<center><img src="img/gpk-eula.png" alt="[img]"/></center>
-+<center><img src="img/gpk-eula.png" alt=""/></center>
- <p class="caption">EULA dialog</p>
--<center><img src="img/gpk-remove-confirm.png" alt="[img]"/></center>
-+<center><img src="img/gpk-remove-confirm.png" alt=""/></center>
- <p class="caption">Remove check warning</p>
--<center><img src="img/gpk-repo-auth.png" alt="[img]"/></center>
-+<center><img src="img/gpk-repo-auth.png" alt=""/></center>
- <p class="caption">Repository authentication</p>
--<center><img src="img/gpk-repo.png" alt="[img]"/></center>
-+<center><img src="img/gpk-repo.png" alt=""/></center>
- <p class="caption">Repository viewer</p>
--<center><img src="img/gpk-backend-status.png" alt="[img]"/></center>
-+<center><img src="img/gpk-backend-status.png" alt=""/></center>
- <p class="caption">PackageKit backend status</p>
--<center><img src="img/gpk-updates-warning.png" alt="[img]"/></center>
-+<center><img src="img/gpk-updates-warning.png" alt=""/></center>
- <p class="caption">Libnotify updates warning</p>
--<center><img src="img/gpk-waiting.png" alt="[img]"/></center>
-+<center><img src="img/gpk-waiting.png" alt=""/></center>
- <p class="caption">Tasks waiting</p>
--<center><img src="img/gpk-battery.png" alt="[img]"/></center>
-+<center><img src="img/gpk-battery.png" alt=""/></center>
- <p class="caption">Intergration with gnome-power-manager</p>
--<center><img src="img/gpk-inhibit.png" alt="[img]"/></center>
-+<center><img src="img/gpk-inhibit.png" alt=""/></center>
- <p class="caption">Inhibit with gnome-power-manager</p>
--<center><img src="img/gpk-require-restart.png" alt="[img]"/></center>
-+<center><img src="img/gpk-require-restart.png" alt=""/></center>
- <p class="caption">We sometimes need to do a restart</p>
--<center><img src="img/gpk-auto-update.png" alt="[img]"/></center>
-+<center><img src="img/gpk-auto-update.png" alt=""/></center>
- <p class="caption">Auto update install dialog</p>
- <h1><a name="kde">KDE Screenshots</a></h1>
--<center><img src="img/kpk-search.png" alt="[img]"/></center>
-+<center><img src="img/kpk-search.png" alt=""/></center>
- <p class="caption">KPackageKit Searching</p>
--<center><img src="img/kpk-information.png" alt="[img]"/></center>
-+<center><img src="img/kpk-information.png" alt=""/></center>
- <p class="caption">KPackageKit Package Information</p>
--<center><img src="img/pk-opensuse-updater.png" alt="[img]"/></center>
-+<center><img src="img/pk-opensuse-updater.png" alt=""/></center>
- <p class="caption">OpenSuse Updater</p>
- <h1><a name="moko">OpenMoko Screenshots</a></h1>
--<center><img src="img/assassin.png" alt="[img]"/></center>
-+<center><img src="img/assassin.png" alt=""/></center>
- <p class="caption">Assassin</p>
- <p>Back to the <a href="index.html">main page</a></p>
-diff --git a/docs/html/pk-using.html b/docs/html/pk-using.html
-index cc455c7..b2b028e 100644
---- a/docs/html/pk-using.html
-+++ b/docs/html/pk-using.html
-@@ -9,9 +9,9 @@
- <table align="center" class="title">
- <tr>
-- <td><img src="img/packagekit.png" alt="[img]"/></td>
-+ <td><img src="img/packagekit.png" alt=""/></td>
-  <td width="95%" valign="middle"><p class="title">How do I use PackageKit?</p></td>
-- <td><img src="img/packagekit.png" alt="[img]"/></td>
-+ <td><img src="img/packagekit.png" alt=""/></td>
- </tr>
- </table>
-diff --git a/docs/spec/pk-concepts.xml b/docs/spec/pk-concepts.xml
-index 312c5a4..0b75b10 100644
---- a/docs/spec/pk-concepts.xml
-+++ b/docs/spec/pk-concepts.xml
-@@ -127,6 +127,13 @@
-               This allows the used to choose non-native packages if a multi-lib policy is allowed.
-             </entry>
-           </row>
-+          <row>
-+            <entry><literal>source</literal> or <literal>~source</literal></entry>
-+            <entry>
-+              The source filter will only return source packages.
-+              These are typically useful when rebuilding other packages.
-+            </entry>
-+          </row>
-         </tbody>
-       </tgroup>
-     </informaltable>
-diff --git a/etc/PackageKit.conf.in b/etc/PackageKit.conf.in
-index a6af99b..8f9bd57 100644
---- a/etc/PackageKit.conf.in
-+++ b/etc/PackageKit.conf.in
-@@ -31,3 +31,13 @@ ShutdownTimeout=300
- # default=@defaultbackend@
- DefaultBackend=@defaultbackend@
-+# Proxy settings, uncomment as required
-+#
-+# NOTE: PackageKit does not use these settings, they are passed to backends.
-+# Backends may ignore these values, or they may be updated from the session.
-+#
-+# They are in the format username:password@server:port
-+#
-+# ProxyHTTP=username:password@server.lan:8080
-+# ProxyFTP=username:password@server.lan:21
-+
-diff --git a/libpackagekit/Makefile.am b/libpackagekit/Makefile.am
-index 6b8c6b8..aeafe44 100644
---- a/libpackagekit/Makefile.am
-+++ b/libpackagekit/Makefile.am
-@@ -37,6 +37,7 @@ libpackagekit_include_HEADERS =                                      \
-       pk-connection.h                                         \
-       pk-package-id.h                                         \
-       pk-package-ids.h                                        \
-+      pk-package-item.h                                       \
-       pk-package-list.h                                       \
-       pk-enum.h                                               \
-       pk-common.h                                             \
-@@ -59,6 +60,8 @@ libpackagekit_la_SOURCES =                                   \
-       pk-package-id.h                                         \
-       pk-package-ids.c                                        \
-       pk-package-ids.h                                        \
-+      pk-package-item.c                                       \
-+      pk-package-item.h                                       \
-       pk-package-list.c                                       \
-       pk-package-list.h                                       \
-       pk-enum.h                                               \
-diff --git a/libpackagekit/pk-enum.c b/libpackagekit/pk-enum.c
-index b5b6ac3..5743dcb 100644
---- a/libpackagekit/pk-enum.c
-+++ b/libpackagekit/pk-enum.c
-@@ -193,6 +193,8 @@ static PkEnumMatch enum_filter[] = {
-       {PK_FILTER_ENUM_NOT_NEWEST,             "~newest"},
-       {PK_FILTER_ENUM_ARCH,                   "arch"},
-       {PK_FILTER_ENUM_NOT_ARCH,               "~arch"},
-+      {PK_FILTER_ENUM_SOURCE,                 "source"},
-+      {PK_FILTER_ENUM_NOT_SOURCE,             "~source"},
-       {0, NULL}
- };
-diff --git a/libpackagekit/pk-enum.h b/libpackagekit/pk-enum.h
-index 33e8a91..e616b64 100644
---- a/libpackagekit/pk-enum.h
-+++ b/libpackagekit/pk-enum.h
-@@ -182,7 +182,9 @@ typedef enum {
-       PK_FILTER_ENUM_NOT_NEWEST               = 1 << 15,
-       PK_FILTER_ENUM_ARCH                     = 1 << 16,
-       PK_FILTER_ENUM_NOT_ARCH                 = 1 << 17,
--      PK_FILTER_ENUM_UNKNOWN                  = 1 << 18
-+      PK_FILTER_ENUM_SOURCE                   = 1 << 18,
-+      PK_FILTER_ENUM_NOT_SOURCE               = 1 << 19,
-+      PK_FILTER_ENUM_UNKNOWN                  = 1 << 20
- } PkFilterEnum;
- /**
-diff --git a/libpackagekit/pk-package-item.c b/libpackagekit/pk-package-item.c
-new file mode 100644
-index 0000000..87905dc
---- /dev/null
-+++ b/libpackagekit/pk-package-item.c
-@@ -0,0 +1,190 @@
-+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
-+ *
-+ * Copyright (C) 2007-2008 Richard Hughes <richard@hughsie.com>
-+ *
-+ * Licensed under the GNU General Public License Version 2
-+ *
-+ * 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 2 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, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ */
-+
-+/**
-+ * SECTION:pk-package-item
-+ * @short_description: A cached Package structure
-+ *
-+ * These provide a way to query and store a single package.
-+ */
-+
-+#include "config.h"
-+
-+#include <stdlib.h>
-+#include <stdio.h>
-+#include <time.h>
-+#include <errno.h>
-+
-+#include <string.h>
-+#include <sys/time.h>
-+#include <sys/types.h>
-+#ifdef HAVE_UNISTD_H
-+#include <unistd.h>
-+#endif /* HAVE_UNISTD_H */
-+
-+#include <glib/gi18n.h>
-+
-+#include "pk-debug.h"
-+#include "pk-common.h"
-+#include "pk-package-item.h"
-+
-+/**
-+ * pk_package_item_new:
-+ **/
-+PkPackageItem *
-+pk_package_item_new (PkInfoEnum info, const gchar *package_id, const gchar *summary)
-+{
-+      PkPackageItem *item;
-+
-+      g_return_val_if_fail (package_id != NULL, FALSE);
-+
-+      pk_debug ("adding to cache item package %s, %s, %s", pk_info_enum_to_text (info), package_id, summary);
-+      item = g_new0 (PkPackageItem, 1);
-+      item->info = info;
-+      item->package_id = g_strdup (package_id);
-+      item->summary = g_strdup (summary);
-+      return item;
-+}
-+
-+/**
-+ * pk_package_item_free:
-+ **/
-+gboolean
-+pk_package_item_free (PkPackageItem *item)
-+{
-+      if (item == NULL) {
-+              return FALSE;
-+      }
-+      g_free (item->package_id);
-+      g_free (item->summary);
-+      g_free (item);
-+      return TRUE;
-+}
-+
-+/**
-+ * pk_package_item_equal:
-+ *
-+ * Only compares the package_id's and the info enum
-+ **/
-+gboolean
-+pk_package_item_equal (PkPackageItem *item1, PkPackageItem *item2)
-+{
-+      if (item1 == NULL || item2 == NULL) {
-+              return FALSE;
-+      }
-+      return (item1->info == item2->info &&
-+              pk_strequal (item1->package_id, item2->package_id));
-+}
-+
-+/**
-+ * pk_package_item_copy:
-+ *
-+ * Copy a PkPackageItem
-+ **/
-+PkPackageItem *
-+pk_package_item_copy (PkPackageItem *item)
-+{
-+      g_return_val_if_fail (item != NULL, NULL);
-+      return pk_package_item_new (item->info, item->package_id, item->summary);
-+}
-+
-+/***************************************************************************
-+ ***                          MAKE CHECK TESTS                           ***
-+ ***************************************************************************/
-+#ifdef PK_BUILD_TESTS
-+#include <libselftest.h>
-+
-+void
-+libst_package_item (LibSelfTest *test)
-+{
-+      PkPackageItem *item1;
-+      PkPackageItem *item2;
-+      PkPackageItem *item3;
-+      gboolean ret;
-+
-+      if (libst_start (test, "PkPackageItem", CLASS_AUTO) == FALSE) {
-+              return;
-+      }
-+
-+      /************************************************************/
-+      libst_title (test, "add entry");
-+      item1 = pk_package_item_new (PK_INFO_ENUM_INSTALLED, "gnome;1.23;i386;data", "GNOME!");
-+      if (item1 != NULL) {
-+              libst_success (test, NULL);
-+      } else {
-+              libst_failed (test, NULL);
-+      }
-+
-+      /************************************************************/
-+      libst_title (test, "add entry");
-+      item2 = pk_package_item_new (PK_INFO_ENUM_INSTALLED, "gnome;1.23;i386;data", "GNOME foo!");
-+      if (item2 != NULL) {
-+              libst_success (test, NULL);
-+      } else {
-+              libst_failed (test, NULL);
-+      }
-+
-+      /************************************************************/
-+      libst_title (test, "copy entry");
-+      item3 = pk_package_item_copy (item2);
-+      if (item3 != NULL) {
-+              libst_success (test, NULL);
-+      } else {
-+              libst_failed (test, NULL);
-+      }
-+
-+      /************************************************************/
-+      libst_title (test, "check equal");
-+      ret = pk_package_item_equal (item1, item3);
-+      if (ret) {
-+              libst_success (test, NULL);
-+      } else {
-+              libst_failed (test, NULL);
-+      }
-+
-+      pk_package_item_free (item2);
-+      pk_package_item_free (item3);
-+
-+      /************************************************************/
-+      libst_title (test, "add entry");
-+      item2 = pk_package_item_new (PK_INFO_ENUM_INSTALLED, "gnome-do;1.23;i386;data", "GNOME doo!");
-+      if (item2 != NULL) {
-+              libst_success (test, NULL);
-+      } else {
-+              libst_failed (test, NULL);
-+      }
-+
-+      /************************************************************/
-+      libst_title (test, "check !equal");
-+      ret = pk_package_item_equal (item1, item2);
-+      if (!ret) {
-+              libst_success (test, NULL);
-+      } else {
-+              libst_failed (test, NULL);
-+      }
-+
-+      pk_package_item_free (item1);
-+      pk_package_item_free (item2);
-+
-+      libst_end (test);
-+}
-+#endif
-+
-diff --git a/libpackagekit/pk-package-item.h b/libpackagekit/pk-package-item.h
-new file mode 100644
-index 0000000..c41a6ea
---- /dev/null
-+++ b/libpackagekit/pk-package-item.h
-@@ -0,0 +1,48 @@
-+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
-+ *
-+ * Copyright (C) 2008 Richard Hughes <richard@hughsie.com>
-+ *
-+ * Licensed under the GNU General Public License Version 2
-+ *
-+ * 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 2 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, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ */
-+
-+#ifndef __PK_PACKAGE_ITEM_H
-+#define __PK_PACKAGE_ITEM_H
-+
-+#include <glib-object.h>
-+#include <pk-enum.h>
-+
-+/**
-+ * PkPackageItem:
-+ *
-+ * A cached store for the complete Package object
-+ */
-+typedef struct {
-+      PkInfoEnum               info;
-+      gchar                   *package_id;
-+      gchar                   *summary;
-+} PkPackageItem;
-+
-+PkPackageItem *pk_package_item_new                    (PkInfoEnum              info,
-+                                                       const gchar            *package_id,
-+                                                       const gchar            *summary);
-+gboolean       pk_package_item_free                   (PkPackageItem          *item);
-+PkPackageItem *pk_package_item_copy                   (PkPackageItem          *item);
-+gboolean       pk_package_item_equal                  (PkPackageItem          *item1,
-+                                                       PkPackageItem          *item2);
-+
-+#endif /* __PK_PACKAGE_ITEM_H */
-+
-diff --git a/libpackagekit/pk-package-list.c b/libpackagekit/pk-package-list.c
-index b0a1a71..5d95e1b 100644
---- a/libpackagekit/pk-package-list.c
-+++ b/libpackagekit/pk-package-list.c
-@@ -45,6 +45,7 @@
- #include "pk-debug.h"
- #include "pk-common.h"
- #include "pk-package-id.h"
-+#include "pk-package-item.h"
- #include "pk-package-list.h"
- static void     pk_package_list_class_init    (PkPackageListClass *klass);
-@@ -77,16 +78,42 @@ pk_package_list_add (PkPackageList *plist, PkInfoEnum info, const gchar *package
-       g_return_val_if_fail (package_id != NULL, FALSE);
-       pk_debug ("adding to cache array package %s, %s, %s", pk_info_enum_to_text (info), package_id, summary);
--      item = g_new0 (PkPackageItem, 1);
--      item->info = info;
--      item->package_id = g_strdup (package_id);
--      item->summary = g_strdup (summary);
-+      item = pk_package_item_new (info, package_id, summary);
-       g_ptr_array_add (plist->priv->array, item);
-       return TRUE;
- }
- /**
-+ * pk_package_list_add_item:
-+ *
-+ * Makes a deep copy, and adds to the array
-+ **/
-+gboolean
-+pk_package_list_add_item (PkPackageList *plist, PkPackageItem *item)
-+{
-+      gboolean ret;
-+      PkPackageItem *item_new;
-+
-+      g_return_val_if_fail (PK_IS_PACKAGE_LIST (plist), FALSE);
-+      g_return_val_if_fail (item != NULL, FALSE);
-+
-+      ret = pk_package_list_contains_item (plist, item);
-+      if (ret) {
-+              pk_debug ("already added item");
-+              return FALSE;
-+      }
-+
-+      pk_debug ("adding to cache array package %s, %s, %s",
-+                pk_info_enum_to_text (item->info), item->package_id, item->summary);
-+
-+      item_new = pk_package_item_copy (item);
-+      g_ptr_array_add (plist->priv->array, item_new);
-+
-+      return TRUE;
-+}
-+
-+/**
-  * pk_package_list_get_string:
-  **/
- gchar *
-@@ -152,9 +179,7 @@ pk_package_list_clear (PkPackageList *plist)
-       while (plist->priv->array->len > 0) {
-               item = g_ptr_array_index (plist->priv->array, 0);
--              g_free (item->package_id);
--              g_free (item->summary);
--              g_free (item);
-+              pk_package_item_free (item);
-               g_ptr_array_remove_index_fast (plist->priv->array, 0);
-       }
-       return TRUE;
-@@ -186,6 +211,31 @@ pk_package_list_contains (PkPackageList *plist, const gchar *package_id)
- }
- /**
-+ * pk_package_list_contains_item:
-+ **/
-+gboolean
-+pk_package_list_contains_item (PkPackageList *plist, PkPackageItem *item)
-+{
-+      PkPackageItem *item_temp;
-+      guint i;
-+      guint length;
-+      gboolean ret = FALSE;
-+
-+      g_return_val_if_fail (PK_IS_PACKAGE_LIST (plist), FALSE);
-+      g_return_val_if_fail (item != NULL, FALSE);
-+
-+      length = plist->priv->array->len;
-+      for (i=0; i<length; i++) {
-+              item_temp = g_ptr_array_index (plist->priv->array, i);
-+              ret = pk_package_item_equal (item_temp, item);
-+              if (ret) {
-+                      break;
-+              }
-+      }
-+      return ret;
-+}
-+
-+/**
-  * pk_package_list_class_init:
-  * @klass: The PkPackageListClass
-  **/
-diff --git a/libpackagekit/pk-package-list.h b/libpackagekit/pk-package-list.h
-index 9178f77..9734af4 100644
---- a/libpackagekit/pk-package-list.h
-+++ b/libpackagekit/pk-package-list.h
-@@ -25,6 +25,8 @@
- #include <glib-object.h>
- #include <pk-enum.h>
-+#include "pk-package-item.h"
-+
- G_BEGIN_DECLS
- #define PK_TYPE_PACKAGE_LIST          (pk_package_list_get_type ())
-@@ -49,26 +51,18 @@ struct _PkPackageListClass
-       GObjectClass    parent_class;
- };
--/**
-- * PkPackageItem:
-- *
-- * A cached store for the complete Package object
-- */
--typedef struct
--{
--      PkInfoEnum               info;
--      gchar                   *package_id;
--      gchar                   *summary;
--} PkPackageItem;
--
- GType          pk_package_list_get_type               (void) G_GNUC_CONST;
- PkPackageList *pk_package_list_new                    (void);
- gboolean       pk_package_list_add                    (PkPackageList          *plist,
-                                                        PkInfoEnum              info,
-                                                        const gchar            *package_id,
-                                                        const gchar            *summary);
-+gboolean       pk_package_list_add_item               (PkPackageList          *plist,
-+                                                       PkPackageItem          *item);
- gboolean       pk_package_list_contains               (PkPackageList          *plist,
-                                                        const gchar            *package_id);
-+gboolean       pk_package_list_contains_item          (PkPackageList          *plist,
-+                                                       PkPackageItem          *item);
- gchar         *pk_package_list_get_string             (PkPackageList          *plist)
-                                                        G_GNUC_WARN_UNUSED_RESULT;
- guint          pk_package_list_get_size               (PkPackageList          *plist);
-diff --git a/libpackagekit/pk-self-test.c b/libpackagekit/pk-self-test.c
-index 62e225b..bf151fb 100644
---- a/libpackagekit/pk-self-test.c
-+++ b/libpackagekit/pk-self-test.c
-@@ -29,6 +29,7 @@
- /* prototypes */
- void libst_package_id (LibSelfTest *test);
- void libst_package_ids (LibSelfTest *test);
-+void libst_package_item (LibSelfTest *test);
- void libst_package_list (LibSelfTest *test);
- void libst_enum (LibSelfTest *test);
- void libst_common (LibSelfTest *test);
-@@ -51,6 +52,7 @@ main (int argc, char **argv)
-       libst_common (&test);
-       libst_package_id (&test);
-       libst_package_ids (&test);
-+      libst_package_item (&test);
-       libst_package_list (&test);
-       libst_enum (&test);
-       libst_extra (&test);
-diff --git a/python/packagekit/daemonBackend.py b/python/packagekit/daemonBackend.py
-index 3711f01..5253b39 100644
---- a/python/packagekit/daemonBackend.py
-+++ b/python/packagekit/daemonBackend.py
-@@ -789,6 +789,21 @@ class PackageKitBaseBackend(dbus.service.Object):
-         self.Finished(EXIT_FAILED)
-     @dbus.service.method(PACKAGEKIT_DBUS_INTERFACE,
-+                         in_signature='ss', out_signature='')
-+    def SetProxy(self, proxy_http, proxy_ftp):
-+        '''
-+        Set the proxy
-+        '''
-+        pklog.info("SetProxy(%s, %s)" % (proxy_http, proxy_ftp))
-+        self.doSetProxy(proxy_http, proxy_ftp)
-+
-+    def doSetProxy(self, proxy_http, proxy_ftp):
-+        '''
-+        Should be replaced in the corresponding backend sub class
-+        '''
-+        # do not use Finished() in this method
-+
-+    @dbus.service.method(PACKAGEKIT_DBUS_INTERFACE,
-                          in_signature='s', out_signature='')
-     def InstallPublicKey(self, keyurl):
-         '''
-diff --git a/src/pk-backend-dbus.c b/src/pk-backend-dbus.c
-index b06e584..4c6837a 100644
---- a/src/pk-backend-dbus.c
-+++ b/src/pk-backend-dbus.c
-@@ -123,16 +123,6 @@ pk_backend_dbus_sub_percentage_changed_cb (DBusGProxy *proxy, guint sub_percenta
- }
- /**
-- * pk_backend_dbus_no_percentage_updates_cb:
-- **/
--static void
--pk_backend_dbus_no_percentage_updates_cb (DBusGProxy *proxy, PkBackendDbus *backend_dbus)
--{
--      pk_debug ("got signal");
--      pk_backend_no_percentage_updates (backend_dbus->priv->backend);
--}
--
--/**
-  * pk_backend_dbus_package_cb:
-  **/
- static void
-@@ -325,8 +315,6 @@ pk_backend_dbus_remove_callbacks (PkBackendDbus *backend_dbus)
-                                       G_CALLBACK (pk_backend_dbus_percentage_changed_cb), backend_dbus);
-       dbus_g_proxy_disconnect_signal (proxy, "SubPercentageChanged",
-                                       G_CALLBACK (pk_backend_dbus_sub_percentage_changed_cb), backend_dbus);
--      dbus_g_proxy_disconnect_signal (proxy, "NoPercentageChanged",
--                                      G_CALLBACK (pk_backend_dbus_no_percentage_updates_cb), backend_dbus);
-       dbus_g_proxy_disconnect_signal (proxy, "Package",
-                                       G_CALLBACK (pk_backend_dbus_package_cb), backend_dbus);
-       dbus_g_proxy_disconnect_signal (proxy, "Details",
-@@ -353,6 +341,31 @@ pk_backend_dbus_remove_callbacks (PkBackendDbus *backend_dbus)
- }
- /**
-+ * pk_backend_dbus_set_proxy:
-+ **/
-+static gboolean
-+pk_backend_dbus_set_proxy (PkBackendDbus *backend_dbus, const gchar *proxy_http, const gchar *proxy_ftp)
-+{
-+      gboolean ret;
-+      GError *error = NULL;
-+
-+      g_return_val_if_fail (PK_IS_BACKEND_DBUS (backend_dbus), FALSE);
-+      g_return_val_if_fail (backend_dbus->priv->proxy != NULL, FALSE);
-+
-+      /* new sync method call */
-+      pk_backend_dbus_time_reset (backend_dbus);
-+      ret = dbus_g_proxy_call (backend_dbus->priv->proxy, "SetProxy", &error,
-+                               G_TYPE_STRING, proxy_http,
-+                               G_TYPE_STRING, proxy_ftp,
-+                               G_TYPE_INVALID, G_TYPE_INVALID);
-+      if (error != NULL) {
-+              pk_warning ("%s", error->message);
-+              g_error_free (error);
-+      }
-+      return ret;
-+}
-+
-+/**
-  * pk_backend_dbus_set_name:
-  **/
- gboolean
-@@ -385,7 +398,6 @@ pk_backend_dbus_set_name (PkBackendDbus *backend_dbus, const gchar *service)
-                                G_TYPE_UINT, G_TYPE_INVALID);
-       dbus_g_proxy_add_signal (proxy, "SubPercentageChanged",
-                                G_TYPE_UINT, G_TYPE_INVALID);
--      dbus_g_proxy_add_signal (proxy, "NoPercentageChanged", G_TYPE_INVALID);
-       dbus_g_proxy_add_signal (proxy, "Package",
-                                G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
-       dbus_g_proxy_add_signal (proxy, "Details",
-@@ -424,8 +436,6 @@ pk_backend_dbus_set_name (PkBackendDbus *backend_dbus, const gchar *service)
-                                    G_CALLBACK (pk_backend_dbus_percentage_changed_cb), backend_dbus, NULL);
-       dbus_g_proxy_connect_signal (proxy, "SubPercentageChanged",
-                                    G_CALLBACK (pk_backend_dbus_sub_percentage_changed_cb), backend_dbus, NULL);
--      dbus_g_proxy_connect_signal (proxy, "NoPercentageChanged",
--                                   G_CALLBACK (pk_backend_dbus_no_percentage_updates_cb), backend_dbus, NULL);
-       dbus_g_proxy_connect_signal (proxy, "Package",
-                                    G_CALLBACK (pk_backend_dbus_package_cb), backend_dbus, NULL);
-       dbus_g_proxy_connect_signal (proxy, "Details",
-@@ -465,6 +475,18 @@ pk_backend_dbus_set_name (PkBackendDbus *backend_dbus, const gchar *service)
-               pk_backend_finished (backend_dbus->priv->backend);
-               g_error_free (error);
-       }
-+
-+      /* set the proxy */
-+      if (ret) {
-+              gchar *proxy_http;
-+              gchar *proxy_ftp;
-+              proxy_http = pk_backend_get_proxy_http (backend_dbus->priv->backend);
-+              proxy_ftp = pk_backend_get_proxy_http (backend_dbus->priv->backend);
-+              pk_backend_dbus_set_proxy (backend_dbus, proxy_http, proxy_ftp);
-+              g_free (proxy_http);
-+              g_free (proxy_ftp);
-+      }
-+
-       if (ret) {
-               pk_backend_dbus_time_check (backend_dbus);
-       }
-diff --git a/src/pk-backend-internal.h b/src/pk-backend-internal.h
-index 2213fed..2bffaff 100644
---- a/src/pk-backend-internal.h
-+++ b/src/pk-backend-internal.h
-@@ -59,6 +59,9 @@ gboolean      pk_backend_reset                       (PkBackend      *backend);
- gboolean       pk_backend_set_name                    (PkBackend      *backend,
-                                                        const gchar    *name)
-                                                        G_GNUC_WARN_UNUSED_RESULT;
-+gboolean       pk_backend_set_proxy                   (PkBackend      *backend,
-+                                                       const gchar    *proxy_http,
-+                                                       const gchar    *proxy_ftp);
- gchar         *pk_backend_get_name                    (PkBackend      *backend)
-                                                        G_GNUC_WARN_UNUSED_RESULT;
- gboolean       pk_backend_get_backend_detail          (PkBackend      *backend,
-diff --git a/src/pk-backend-spawn.c b/src/pk-backend-spawn.c
-index f9e8b68..f9c9f12 100644
---- a/src/pk-backend-spawn.c
-+++ b/src/pk-backend-spawn.c
-@@ -313,7 +313,7 @@ pk_backend_spawn_parse_stdout (PkBackendSpawn *backend_spawn, const gchar *line)
-                       ret = FALSE;
-                       goto out;
-               }
--              pk_backend_no_percentage_updates (backend_spawn->priv->backend);
-+              pk_backend_set_percentage (backend_spawn->priv->backend, PK_BACKEND_PERCENTAGE_INVALID);
-       } else if (pk_strequal (command, "repo-signature-required")) {
-               if (size != 9+99) {
-@@ -440,6 +440,44 @@ pk_backend_spawn_helper_new (PkBackendSpawn *backend_spawn)
- }
- /**
-+ * pk_backend_spawn_get_envp:
-+ *
-+ * Return all the environment variables the script will need
-+ **/
-+static gchar **
-+pk_backend_spawn_get_envp (PkBackendSpawn *backend_spawn)
-+{
-+      gchar **envp;
-+      gchar *value;
-+      gchar *line;
-+      GPtrArray *array;
-+
-+      array = g_ptr_array_new ();
-+
-+      /* http_proxy */
-+      value = pk_backend_get_proxy_http (backend_spawn->priv->backend);
-+      if (!pk_strzero (value)) {
-+              line = g_strdup_printf ("%s=%s", "http_proxy", value);
-+              pk_debug ("setting evp '%s'", line);
-+              g_ptr_array_add (array, line);
-+      }
-+      g_free (value);
-+
-+      /* ftp_proxy */
-+      value = pk_backend_get_proxy_ftp (backend_spawn->priv->backend);
-+      if (!pk_strzero (value)) {
-+              line = g_strdup_printf ("%s=%s", "ftp_proxy", value);
-+              pk_debug ("setting evp '%s'", line);
-+              g_ptr_array_add (array, line);
-+      }
-+      g_free (value);
-+
-+      envp = pk_ptr_array_to_argv (array);
-+      g_ptr_array_free (array, TRUE);
-+      return envp;
-+}
-+
-+/**
-  * pk_backend_spawn_helper_va_list:
-  **/
- static gboolean
-@@ -448,6 +486,7 @@ pk_backend_spawn_helper_va_list (PkBackendSpawn *backend_spawn, const gchar *exe
-       gboolean ret;
-       gchar *filename;
-       gchar **argv;
-+      gchar **envp;
-       g_return_val_if_fail (PK_IS_BACKEND_SPAWN (backend_spawn), FALSE);
-@@ -476,7 +515,8 @@ pk_backend_spawn_helper_va_list (PkBackendSpawn *backend_spawn, const gchar *exe
-       argv[0] = g_strdup (filename);
-       pk_backend_spawn_helper_new (backend_spawn);
--      ret = pk_spawn_argv (backend_spawn->priv->spawn, argv);
-+      envp = pk_backend_spawn_get_envp (backend_spawn);
-+      ret = pk_spawn_argv (backend_spawn->priv->spawn, argv, envp);
-       if (!ret) {
-               pk_backend_spawn_helper_delete (backend_spawn);
-               pk_backend_error_code (backend_spawn->priv->backend, PK_ERROR_ENUM_INTERNAL_ERROR,
-diff --git a/src/pk-backend.c b/src/pk-backend.c
-index 225c488..37ed024 100644
---- a/src/pk-backend.c
-+++ b/src/pk-backend.c
-@@ -33,6 +33,7 @@
- #include <glib/gprintf.h>
- #include <pk-network.h>
-+#include "pk-package-item.h"
- #include "pk-debug.h"
- #include "pk-common.h"
- #include "pk-marshal.h"
-@@ -44,13 +45,6 @@
- #define PK_BACKEND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PK_TYPE_BACKEND, PkBackendPrivate))
- /**
-- * PK_BACKEND_PERCENTAGE_INVALID:
-- *
-- * The unknown percentage value
-- */
--#define PK_BACKEND_PERCENTAGE_INVALID         101
--
--/**
-  * PK_BACKEND_PERCENTAGE_DEFAULT:
-  *
-  * The default percentage value, should never be emitted, but should be
-@@ -84,12 +78,15 @@ struct _PkBackendPrivate
-       GHashTable              *eulas;
-       gchar                   *name;
-       gchar                   *c_tid;
-+      gchar                   *proxy_http;
-+      gchar                   *proxy_ftp;
-       gboolean                 locked;
-       gboolean                 set_error;
-       gboolean                 set_signature;
-       gboolean                 set_eula;
-       gboolean                 has_sent_package;
-       PkNetwork               *network;
-+      PkPackageItem           *last_package;
-       PkRoleEnum               role; /* this never changes for the lifetime of a transaction */
-       PkStatusEnum             status; /* this changes */
-       PkExitEnum               exit;
-@@ -592,6 +589,44 @@ out:
- }
- /**
-+ * pk_backend_set_proxy:
-+ **/
-+gboolean
-+pk_backend_set_proxy (PkBackend       *backend, const gchar *proxy_http, const gchar *proxy_ftp)
-+{
-+      g_return_val_if_fail (PK_IS_BACKEND (backend), FALSE);
-+      g_free (backend->priv->proxy_http);
-+      g_free (backend->priv->proxy_ftp);
-+      backend->priv->proxy_http = g_strdup (proxy_http);
-+      backend->priv->proxy_ftp = g_strdup (proxy_ftp);
-+      return TRUE;
-+}
-+
-+/**
-+ * pk_backend_get_proxy_http:
-+ *
-+ * Return value: proxy string in the form username:password@server:port
-+ **/
-+gchar *
-+pk_backend_get_proxy_http (PkBackend *backend)
-+{
-+      g_return_val_if_fail (PK_IS_BACKEND (backend), NULL);
-+      return g_strdup (backend->priv->proxy_http);
-+}
-+
-+/**
-+ * pk_backend_get_proxy_ftp:
-+ *
-+ * Return value: proxy string in the form username:password@server:port
-+ **/
-+gchar *
-+pk_backend_get_proxy_ftp (PkBackend *backend)
-+{
-+      g_return_val_if_fail (PK_IS_BACKEND (backend), NULL);
-+      return g_strdup (backend->priv->proxy_ftp);
-+}
-+
-+/**
-  * pk_backend_lock:
-  *
-  * Responsible for initialising the external backend object.
-@@ -803,35 +838,6 @@ pk_backend_set_sub_percentage (PkBackend *backend, guint percentage)
- }
- /**
-- * pk_backend_no_percentage_updates:
-- **/
--gboolean
--pk_backend_no_percentage_updates (PkBackend *backend)
--{
--      g_return_val_if_fail (PK_IS_BACKEND (backend), FALSE);
--      g_return_val_if_fail (backend->priv->locked != FALSE, FALSE);
--
--      /* have we already set an error? */
--      if (backend->priv->set_error) {
--              pk_warning ("already set error, cannot process");
--              return FALSE;
--      }
--
--      /* set the same twice? */
--      if (backend->priv->last_percentage == PK_BACKEND_PERCENTAGE_INVALID) {
--              pk_debug ("duplicate set of %i", PK_BACKEND_PERCENTAGE_INVALID);
--              return FALSE;
--      }
--
--      /* invalidate previous percentage */
--      backend->priv->last_percentage = PK_BACKEND_PERCENTAGE_INVALID;
--
--      /* emit the progress changed signal */
--      pk_backend_emit_progress_changed (backend);
--      return TRUE;
--}
--
--/**
-  * pk_backend_set_status:
-  **/
- gboolean
-@@ -901,11 +907,26 @@ gboolean
- pk_backend_package (PkBackend *backend, PkInfoEnum info, const gchar *package_id, const gchar *summary)
- {
-       gchar *summary_safe;
-+      PkPackageItem *item;
-+      gboolean ret;
-       g_return_val_if_fail (PK_IS_BACKEND (backend), FALSE);
-       g_return_val_if_fail (package_id != NULL, FALSE);
-       g_return_val_if_fail (backend->priv->locked != FALSE, FALSE);
-+      /* check against the old one */
-+      item = pk_package_item_new (info, package_id, summary);
-+      ret = pk_package_item_equal (item, backend->priv->last_package);
-+      if (ret) {
-+              pk_package_item_free (item);
-+              pk_debug ("skipping duplicate %s", package_id);
-+              return FALSE;
-+      }
-+      /* update the 'last' package */
-+      pk_package_item_free (backend->priv->last_package);
-+      backend->priv->last_package = pk_package_item_copy (item);
-+      pk_package_item_free (item);
-+
-       /* have we already set an error? */
-       if (backend->priv->set_error) {
-               pk_warning ("already set error, cannot process");
-@@ -1689,6 +1710,8 @@ pk_backend_finalize (GObject *object)
-       pk_debug ("backend finalise");
-       pk_backend_reset (backend);
-+      g_free (backend->priv->proxy_http);
-+      g_free (backend->priv->proxy_ftp);
-       g_free (backend->priv->name);
-       g_free (backend->priv->c_tid);
-       g_object_unref (backend->priv->time);
-@@ -1818,6 +1841,7 @@ pk_backend_reset (PkBackend *backend)
-       /* TODO: need to wait for Finished() if running */
-+      pk_package_item_free (backend->priv->last_package);
-       backend->priv->set_error = FALSE;
-       backend->priv->set_signature = FALSE;
-       backend->priv->set_eula = FALSE;
-@@ -1825,6 +1849,7 @@ pk_backend_reset (PkBackend *backend)
-       backend->priv->finished = FALSE;
-       backend->priv->has_sent_package = FALSE;
-       backend->priv->thread = NULL;
-+      backend->priv->last_package = NULL;
-       backend->priv->status = PK_STATUS_ENUM_UNKNOWN;
-       backend->priv->exit = PK_EXIT_ENUM_UNKNOWN;
-       backend->priv->role = PK_ROLE_ENUM_UNKNOWN;
-@@ -1855,8 +1880,11 @@ pk_backend_init (PkBackend *backend)
-       backend->priv->handle = NULL;
-       backend->priv->name = NULL;
-       backend->priv->c_tid = NULL;
-+      backend->priv->proxy_http = NULL;
-+      backend->priv->proxy_ftp = NULL;
-       backend->priv->file_changed_func = NULL;
-       backend->priv->file_changed_data = NULL;
-+      backend->priv->last_package = NULL;
-       backend->priv->locked = FALSE;
-       backend->priv->signal_finished = 0;
-       backend->priv->signal_error_timeout = 0;
-diff --git a/src/pk-backend.h b/src/pk-backend.h
-index 95b7fa8..fb17e3c 100644
---- a/src/pk-backend.h
-+++ b/src/pk-backend.h
-@@ -30,6 +30,13 @@
- G_BEGIN_DECLS
-+/**
-+ * PK_BACKEND_PERCENTAGE_INVALID:
-+ *
-+ * The unknown percentage value
-+ */
-+#define PK_BACKEND_PERCENTAGE_INVALID         101
-+
- typedef struct _PkBackend PkBackend;
- /* set the state */
-@@ -51,7 +58,6 @@ gboolean      pk_backend_set_sub_percentage          (PkBackend      *backend,
-                                                        guint           percentage);
- gboolean       pk_backend_set_exit_code               (PkBackend      *backend,
-                                                        PkExitEnum      exit);
--gboolean       pk_backend_no_percentage_updates       (PkBackend      *backend);
- gboolean       pk_backend_set_transaction_data        (PkBackend      *backend,
-                                                        const gchar    *data);
-@@ -66,6 +72,8 @@ gboolean      pk_backend_get_progress                (PkBackend      *backend,
-                                                        guint          *elapsed,
-                                                        guint          *remaining);
- guint          pk_backend_get_runtime                 (PkBackend      *backend);
-+gchar         *pk_backend_get_proxy_ftp               (PkBackend      *backend);
-+gchar         *pk_backend_get_proxy_http              (PkBackend      *backend);
- /* signal helpers */
- gboolean       pk_backend_finished                    (PkBackend      *backend);
-diff --git a/src/pk-engine.c b/src/pk-engine.c
-index db81d36..028a0d0 100644
---- a/src/pk-engine.c
-+++ b/src/pk-engine.c
-@@ -101,6 +101,7 @@ struct PkEnginePrivate
-       PkNetwork               *network;
-       PkSecurity              *security;
-       PkNotify                *notify;
-+      PkConf                  *conf;
-       PkFileMonitor           *file_monitor;
-       PkRoleEnum               actions;
-       PkGroupEnum              groups;
-@@ -579,10 +580,15 @@ pk_engine_init (PkEngine *engine)
-       DBusGConnection *connection;
-       gboolean ret;
-       gchar *filename;
-+      gchar *proxy_http;
-+      gchar *proxy_ftp;
-       engine->priv = PK_ENGINE_GET_PRIVATE (engine);
-       engine->priv->restart_schedule = FALSE;
-+      /* use the config file */
-+      engine->priv->conf = pk_conf_new ();
-+
-       /* setup the backend backend */
-       engine->priv->backend = pk_backend_new ();
-       g_signal_connect (engine->priv->backend, "finished",
-@@ -639,6 +645,13 @@ pk_engine_init (PkEngine *engine)
-                         G_CALLBACK (pk_engine_file_monitor_changed_cb), engine);
-       g_free (filename);
-+      /* set the proxy */
-+      proxy_http = pk_conf_get_string (engine->priv->conf, "ProxyHTTP");
-+      proxy_ftp = pk_conf_get_string (engine->priv->conf, "ProxyFTP");
-+      pk_backend_set_proxy (engine->priv->backend, proxy_http, proxy_ftp);
-+      g_free (proxy_http);
-+      g_free (proxy_ftp);
-+
-       engine->priv->transaction_list = pk_transaction_list_new ();
-       g_signal_connect (engine->priv->transaction_list, "changed",
-                         G_CALLBACK (pk_engine_transaction_list_changed_cb), engine);
-@@ -696,6 +709,7 @@ pk_engine_finalize (GObject *object)
-       g_object_unref (engine->priv->notify);
-       g_object_unref (engine->priv->backend);
-       g_object_unref (engine->priv->cache);
-+      g_object_unref (engine->priv->conf);
-       G_OBJECT_CLASS (pk_engine_parent_class)->finalize (object);
- }
-diff --git a/src/pk-network-unix.c b/src/pk-network-unix.c
-index 11c23a2..74b266c 100644
---- a/src/pk-network-unix.c
-+++ b/src/pk-network-unix.c
-@@ -138,6 +138,11 @@ pk_network_unix_get_network_state (PkNetworkUnix *network_unix)
-                       continue;
-               }
-+              /* is loopback? */
-+              if (pk_strequal (sections[0], "lo")) {
-+                      continue;
-+              }
-+
-               /* is correct parameters? */
-               number_sections = g_strv_length (sections);
-               if (number_sections != 11) {
-@@ -145,9 +150,8 @@ pk_network_unix_get_network_state (PkNetworkUnix *network_unix)
-                       continue;
-               }
--              /* is MTU and gateway nonzero? */
--              if (!pk_strequal (sections[8], "0") &&
--                  !pk_strequal (sections[2], "00000000")) {
-+              /* is gateway nonzero? */
-+              if (!pk_strequal (sections[2], "00000000")) {
-                       pk_debug ("interface %s is valid", sections[0]);
-                       online = TRUE;
-               }
-diff --git a/src/pk-network.c b/src/pk-network.c
-index 9656958..0ad839e 100644
---- a/src/pk-network.c
-+++ b/src/pk-network.c
-@@ -39,6 +39,7 @@
- #ifdef HAVE_UNISTD_H
- #include <unistd.h>
- #endif /* HAVE_UNISTD_H */
-+#include <libgbus.h>
- #include <glib/gi18n.h>
-@@ -67,6 +68,7 @@ struct _PkNetworkPrivate
-       PkNetworkNm             *net_nm;
-       PkNetworkUnix           *net_unix;
-       PkConf                  *conf;
-+      LibGBus                 *nm_bus;
- };
- enum {
-@@ -154,6 +156,7 @@ pk_network_class_init (PkNetworkClass *klass)
- static void
- pk_network_init (PkNetwork *network)
- {
-+      gboolean nm_alive;
-       network->priv = PK_NETWORK_GET_PRIVATE (network);
-       network->priv->conf = pk_conf_new ();
-       network->priv->net_nm = pk_network_nm_new ();
-@@ -167,6 +170,17 @@ pk_network_init (PkNetwork *network)
-       network->priv->use_nm = pk_conf_get_bool (network->priv->conf, "UseNetworkManager");
-       network->priv->use_unix = pk_conf_get_bool (network->priv->conf, "UseNetworkHeuristic");
-+      /* check if NM is on the bus */
-+      network->priv->nm_bus = libgbus_new ();
-+      libgbus_assign (network->priv->nm_bus, LIBGBUS_SYSTEM, "org.freedesktop.NetworkManager");
-+      nm_alive = libgbus_is_connected (network->priv->nm_bus);
-+
-+      /* NetworkManager isn't up, so we can't use it */
-+      if (network->priv->use_nm && !nm_alive) {
-+              pk_warning ("UseNetworkManager true, but org.freedesktop.NetworkManager not up");
-+              network->priv->use_nm = FALSE;
-+      }
-+
- #if !PK_BUILD_NETWORKMANAGER
-       /* check we can actually use the default */
-       if (network->priv->use_nm) {
-@@ -190,6 +204,7 @@ pk_network_finalize (GObject *object)
-       g_return_if_fail (network->priv != NULL);
-       g_object_unref (network->priv->conf);
-+      g_object_unref (network->priv->nm_bus);
-       g_object_unref (network->priv->net_nm);
-       g_object_unref (network->priv->net_unix);
-       G_OBJECT_CLASS (pk_network_parent_class)->finalize (object);
-diff --git a/src/pk-spawn.c b/src/pk-spawn.c
-index 9b415b1..c4622f9 100644
---- a/src/pk-spawn.c
-+++ b/src/pk-spawn.c
-@@ -273,7 +273,7 @@ pk_spawn_kill (PkSpawn *spawn)
-  *
-  **/
- gboolean
--pk_spawn_argv (PkSpawn *spawn, gchar **argv)
-+pk_spawn_argv (PkSpawn *spawn, gchar **argv, gchar **envp)
- {
-       gboolean ret;
-@@ -284,7 +284,7 @@ pk_spawn_argv (PkSpawn *spawn, gchar **argv)
-       spawn->priv->finished = FALSE;
-       /* create spawned object for tracking */
--      ret = g_spawn_async_with_pipes (NULL, argv, NULL,
-+      ret = g_spawn_async_with_pipes (NULL, argv, envp,
-                                G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH,
-                                NULL, NULL, &spawn->priv->child_pid,
-                                NULL, /* stdin */
-@@ -484,6 +484,7 @@ libst_spawn (LibSelfTest *test)
-       gboolean ret;
-       gchar *path;
-       gchar **argv;
-+      gchar **envp;
-       if (libst_start (test, "PkSpawn", CLASS_AUTO) == FALSE) {
-               return;
-@@ -496,7 +497,7 @@ libst_spawn (LibSelfTest *test)
-       libst_title (test, "make sure return error for missing file");
-       mexit = BAD_EXIT;
-       argv = g_strsplit ("pk-spawn-test-xxx.sh", " ", 0);
--      ret = pk_spawn_argv (spawn, argv);
-+      ret = pk_spawn_argv (spawn, argv, NULL);
-       g_strfreev (argv);
-       if (ret == FALSE) {
-               libst_success (test, "failed to run invalid file");
-@@ -517,7 +518,7 @@ libst_spawn (LibSelfTest *test)
-       mexit = -1;
-       path = pk_test_get_data ("pk-spawn-test.sh");
-       argv = g_strsplit (path, " ", 0);
--      ret = pk_spawn_argv (spawn, argv);
-+      ret = pk_spawn_argv (spawn, argv, NULL);
-       g_free (path);
-       g_strfreev (argv);
-       if (ret) {
-@@ -558,11 +559,34 @@ libst_spawn (LibSelfTest *test)
-       new_spawn_object (test, &spawn);
-       /************************************************************/
-+      libst_title (test, "make sure we set the proxy");
-+      mexit = -1;
-+      path = pk_test_get_data ("pk-spawn-proxy.sh");
-+      argv = g_strsplit (path, " ", 0);
-+      envp = g_strsplit ("http_proxy=username:password@server:port "
-+                         "ftp_proxy=username:password@server:port", " ", 0);
-+      ret = pk_spawn_argv (spawn, argv, envp);
-+      g_free (path);
-+      g_strfreev (argv);
-+      if (ret) {
-+              libst_success (test, "ran correct file");
-+      } else {
-+              libst_failed (test, "did not run helper");
-+      }
-+
-+      /* wait for finished */
-+      libst_loopwait (test, 10000);
-+      libst_loopcheck (test);
-+
-+      /* get new object */
-+      new_spawn_object (test, &spawn);
-+
-+      /************************************************************/
-       libst_title (test, "make sure run correct helper, and kill it");
-       mexit = BAD_EXIT;
-       path = pk_test_get_data ("pk-spawn-test.sh");
-       argv = g_strsplit (path, " ", 0);
--      ret = pk_spawn_argv (spawn, argv);
-+      ret = pk_spawn_argv (spawn, argv, NULL);
-       g_free (path);
-       g_strfreev (argv);
-       if (ret) {
-@@ -592,7 +616,7 @@ libst_spawn (LibSelfTest *test)
-       mexit = BAD_EXIT;
-       path = pk_test_get_data ("pk-spawn-test-sigquit.sh");
-       argv = g_strsplit (path, " ", 0);
--      ret = pk_spawn_argv (spawn, argv);
-+      ret = pk_spawn_argv (spawn, argv, NULL);
-       g_free (path);
-       g_strfreev (argv);
-       if (ret) {
-@@ -618,7 +642,7 @@ libst_spawn (LibSelfTest *test)
-       libst_title (test, "run lots of data for profiling");
-       path = pk_test_get_data ("pk-spawn-test-profiling.sh");
-       argv = g_strsplit (path, " ", 0);
--      ret = pk_spawn_argv (spawn, argv);
-+      ret = pk_spawn_argv (spawn, argv, NULL);
-       g_free (path);
-       g_strfreev (argv);
-       if (ret) {
-diff --git a/src/pk-spawn.h b/src/pk-spawn.h
-index 1b20fef..0e58859 100644
---- a/src/pk-spawn.h
-+++ b/src/pk-spawn.h
-@@ -52,7 +52,8 @@ GType                 pk_spawn_get_type                      (void) G_GNUC_CONST;
- PkSpawn               *pk_spawn_new                           (void);
- gboolean       pk_spawn_argv                          (PkSpawn        *spawn,
--                                                       gchar          **argv)
-+                                                       gchar          **argv,
-+                                                       gchar          **envp)
-                                                        G_GNUC_WARN_UNUSED_RESULT;
- gboolean       pk_spawn_kill                          (PkSpawn        *spawn);
index ba8f99d..2b38ffe 100644 (file)
@@ -5,11 +5,13 @@ LICENSE = "GPL"
 DEPENDS = "dbus (>= 1.1.1) dbus-glib glib-2.0 sqlite3 opkg intltool intltool-native (>= 0.37.1)"
 RDEPENDS_${PN} = "opkg"
 PV = "0.2.3+gitr${SRCREV}"
-PR = "r10"
+PR = "r11"
 
 SRC_URI = "git://anongit.freedesktop.org/git/packagekit;protocol=git \
            file://disable-docbook2man.patch;patch=1 \
-           file://d1e096c3267c1c9492041382b954e9327bc8bbec.patch;patch=1"
+           file://01_d1e096c3267c1c9492041382b954e9327bc8bbec.patch;patch=1 \
+          file://02_9ced8313fb12f0f89ad6ced7c0fdc7241ff00d77.patch;patch=1"
+
 
 
 S = "${WORKDIR}/git"